diff options
Diffstat (limited to 'src/contrib/SDL-3.2.20/examples')
114 files changed, 6002 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/examples/CMakeLists.txt b/src/contrib/SDL-3.2.20/examples/CMakeLists.txt new file mode 100644 index 0000000..2a13a03 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/CMakeLists.txt | |||
@@ -0,0 +1,382 @@ | |||
1 | # | ||
2 | # CMake script for building the SDL examples | ||
3 | # | ||
4 | |||
5 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake") | ||
6 | |||
7 | include(CheckIncludeFile) | ||
8 | include(CheckStructHasMember) | ||
9 | include(CMakePushCheckState) | ||
10 | include(sdlcompilers) | ||
11 | |||
12 | if(SDL_EXAMPLES_LINK_SHARED) | ||
13 | set(sdl_name_component SDL3-shared) | ||
14 | else() | ||
15 | set(sdl_name_component SDL3-static) | ||
16 | endif() | ||
17 | set(HAVE_EXAMPLES_LINK_SHARED "${SDL_EXAMPLES_LINK_SHARED}" PARENT_SCOPE) | ||
18 | |||
19 | # CMake incorrectly detects opengl32.lib being present on MSVC ARM64 | ||
20 | if(NOT (MSVC AND SDL_CPU_ARM64)) | ||
21 | # Prefer GLVND, if present | ||
22 | set(OpenGL_GL_PREFERENCE GLVND) | ||
23 | find_package(OpenGL) | ||
24 | endif() | ||
25 | |||
26 | set(SDL_EXAMPLE_EXECUTABLES) | ||
27 | |||
28 | if(CMAKE_RUNTIME_OUTPUT_DIRECTORY) | ||
29 | set(example_bin_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") | ||
30 | if(NOT IS_ABSOLUTE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") | ||
31 | set(example_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") | ||
32 | endif() | ||
33 | else() | ||
34 | set(example_bin_dir "${CMAKE_CURRENT_BINARY_DIR}") | ||
35 | endif() | ||
36 | if(NOT CMAKE_VERSION VERSION_LESS 3.20) | ||
37 | get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||
38 | set(example_bin_dir "${example_bin_dir}$<$<BOOL:${is_multi_config}>:/$<CONFIG>>") | ||
39 | endif() | ||
40 | |||
41 | file(GLOB RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.wav ${CMAKE_CURRENT_SOURCE_DIR}/../test/*.hex) | ||
42 | |||
43 | set(RESOURCE_FILE_NAMES) | ||
44 | set(RESOURCE_FILES_BINDIR) | ||
45 | foreach(resource_file IN LISTS RESOURCE_FILES) | ||
46 | get_filename_component(res_file_name ${resource_file} NAME) | ||
47 | list(APPEND RESOURCE_FILE_NAMES "${res_file_name}") | ||
48 | set(resource_file_bindir "${example_bin_dir}/${res_file_name}") | ||
49 | add_custom_command(OUTPUT "${resource_file_bindir}" | ||
50 | COMMAND "${CMAKE_COMMAND}" -E copy "${resource_file}" "${resource_file_bindir}" | ||
51 | DEPENDS "${resource_file}" | ||
52 | ) | ||
53 | list(APPEND RESOURCE_FILES_BINDIR "${resource_file_bindir}") | ||
54 | endforeach() | ||
55 | add_custom_target(copy-sdl-example-resources | ||
56 | DEPENDS "${RESOURCE_FILES_BINDIR}" | ||
57 | ) | ||
58 | |||
59 | macro(add_sdl_example_executable TARGET) | ||
60 | cmake_parse_arguments(AST "BUILD_DEPENDENT" "" "SOURCES;DATAFILES" ${ARGN}) | ||
61 | if(AST_UNPARSED_ARGUMENTS) | ||
62 | message(FATAL_ERROR "Unknown argument(s): ${AST_UNPARSED_ARGUMENTS}") | ||
63 | endif() | ||
64 | if(NOT AST_SOURCES) | ||
65 | message(FATAL_ERROR "add_sdl_example_executable needs at least one source") | ||
66 | endif() | ||
67 | set(EXTRA_SOURCES "") | ||
68 | if(AST_DATAFILES) | ||
69 | list(APPEND EXTRA_SOURCES ${DATAFILES}) | ||
70 | endif() | ||
71 | if(ANDROID) | ||
72 | add_library(${TARGET} SHARED ${AST_SOURCES} ${EXTRA_SOURCES}) | ||
73 | else() | ||
74 | add_executable(${TARGET} ${AST_SOURCES} ${EXTRA_SOURCES}) | ||
75 | endif() | ||
76 | SDL_AddCommonCompilerFlags(${TARGET}) | ||
77 | target_include_directories(${TARGET} PRIVATE "${SDL3_SOURCE_DIR}/src/video/khronos") | ||
78 | target_link_libraries(${TARGET} PRIVATE SDL3::${sdl_name_component}) | ||
79 | |||
80 | list(APPEND SDL_EXAMPLE_EXECUTABLES ${TARGET}) | ||
81 | if(AST_DATAFILES) | ||
82 | if(PSP OR PS2) | ||
83 | add_custom_command(TARGET ${TARGET} POST_BUILD | ||
84 | COMMAND ${CMAKE_COMMAND} ARGS -E make_directory $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET} | ||
85 | COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${AST_DATAFILES} $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET} | ||
86 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" | ||
87 | ) | ||
88 | else() | ||
89 | add_dependencies(${TARGET} copy-sdl-example-resources) | ||
90 | endif() | ||
91 | if(APPLE) | ||
92 | # Make sure resource files get installed into macOS/iOS .app bundles. | ||
93 | set_target_properties(${TARGET} PROPERTIES RESOURCE "${AST_DATAFILES}") | ||
94 | endif() | ||
95 | if(EMSCRIPTEN) | ||
96 | foreach(res IN LISTS AST_DATAFILES) | ||
97 | get_filename_component(res_name "${res}" NAME) | ||
98 | target_link_options(${TARGET} PRIVATE "SHELL:--embed-file ${res}@${res_name}") | ||
99 | endforeach() | ||
100 | endif() | ||
101 | set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES "$<TARGET_FILE_DIR:${TARGET}>/$<JOIN:${AST_DATAFILES},$<SEMICOLON>$<TARGET_FILE_DIR:${TARGET}>/>") | ||
102 | endif() | ||
103 | |||
104 | if(WINDOWS) | ||
105 | # CET support was added in VS 16.7 | ||
106 | if(MSVC_VERSION GREATER 1926 AND CMAKE_GENERATOR_PLATFORM MATCHES "Win32|x64") | ||
107 | set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -CETCOMPAT") | ||
108 | endif() | ||
109 | elseif(PSP) | ||
110 | target_link_libraries(${TARGET} PRIVATE GL) | ||
111 | elseif(EMSCRIPTEN) | ||
112 | set_property(TARGET ${TARGET} PROPERTY SUFFIX ".html") | ||
113 | target_link_options(${TARGET} PRIVATE -sALLOW_MEMORY_GROWTH=1) | ||
114 | endif() | ||
115 | |||
116 | if(OPENGL_FOUND) | ||
117 | target_compile_definitions(${TARGET} PRIVATE HAVE_OPENGL) | ||
118 | endif() | ||
119 | |||
120 | # FIXME: only add "${SDL3_BINARY_DIR}/include-config-$<LOWER_CASE:$<CONFIG>>" + include paths of external dependencies | ||
121 | target_include_directories(${TARGET} PRIVATE "$<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>") | ||
122 | endmacro() | ||
123 | |||
124 | add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/clear.c) | ||
125 | add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/primitives.c) | ||
126 | add_sdl_example_executable(renderer-lines SOURCES renderer/03-lines/lines.c) | ||
127 | add_sdl_example_executable(renderer-points SOURCES renderer/04-points/points.c) | ||
128 | add_sdl_example_executable(renderer-rectangles SOURCES renderer/05-rectangles/rectangles.c) | ||
129 | add_sdl_example_executable(renderer-textures SOURCES renderer/06-textures/textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
130 | add_sdl_example_executable(renderer-streaming-textures SOURCES renderer/07-streaming-textures/streaming-textures.c) | ||
131 | add_sdl_example_executable(renderer-rotating-textures SOURCES renderer/08-rotating-textures/rotating-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
132 | add_sdl_example_executable(renderer-scaling-textures SOURCES renderer/09-scaling-textures/scaling-textures.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
133 | add_sdl_example_executable(renderer-geometry SOURCES renderer/10-geometry/geometry.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
134 | add_sdl_example_executable(renderer-color-mods SOURCES renderer/11-color-mods/color-mods.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
135 | add_sdl_example_executable(renderer-viewport SOURCES renderer/14-viewport/viewport.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
136 | add_sdl_example_executable(renderer-cliprect SOURCES renderer/15-cliprect/cliprect.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
137 | add_sdl_example_executable(renderer-read-pixels SOURCES renderer/17-read-pixels/read-pixels.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp) | ||
138 | add_sdl_example_executable(renderer-debug-text SOURCES renderer/18-debug-text/debug-text.c) | ||
139 | add_sdl_example_executable(audio-simple-playback SOURCES audio/01-simple-playback/simple-playback.c) | ||
140 | add_sdl_example_executable(audio-simple-playback-callback SOURCES audio/02-simple-playback-callback/simple-playback-callback.c) | ||
141 | add_sdl_example_executable(audio-load-wav SOURCES audio/03-load-wav/load-wav.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav) | ||
142 | 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) | ||
143 | add_sdl_example_executable(input-joystick-polling SOURCES input/01-joystick-polling/joystick-polling.c) | ||
144 | add_sdl_example_executable(input-joystick-events SOURCES input/02-joystick-events/joystick-events.c) | ||
145 | add_sdl_example_executable(camera-read-and-draw SOURCES camera/01-read-and-draw/read-and-draw.c) | ||
146 | add_sdl_example_executable(pen-drawing-lines SOURCES pen/01-drawing-lines/drawing-lines.c) | ||
147 | add_sdl_example_executable(asyncio-load-bitmaps SOURCES asyncio/01-load-bitmaps/load-bitmaps.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/gamepad_front.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/speaker.bmp ${CMAKE_CURRENT_SOURCE_DIR}/../test/icon2x.bmp) | ||
148 | add_sdl_example_executable(demo-snake SOURCES demo/01-snake/snake.c) | ||
149 | add_sdl_example_executable(demo-woodeneye-008 SOURCES demo/02-woodeneye-008/woodeneye-008.c) | ||
150 | add_sdl_example_executable(demo-infinite-monkeys SOURCES demo/03-infinite-monkeys/infinite-monkeys.c) | ||
151 | add_sdl_example_executable(demo-bytepusher SOURCES demo/04-bytepusher/bytepusher.c) | ||
152 | |||
153 | # When you add an example, remember to add the Visual Studio project as well: | ||
154 | # - Add a new example in examples/ | ||
155 | # - Run python VisualC/examples/generate.py | ||
156 | # - Take note of the newly generated .vcxproj files | ||
157 | # - Modify the .vcxproj files if necessary (adding content such as BMP or WAV files) | ||
158 | # - Open VisualC/SDL.sln in Visual Studio or JetBrains Rider | ||
159 | # - Locate the appropriate folder in the Solution Explorer | ||
160 | # - Add the newly generated projects: Right click -> Add -> Existing project... | ||
161 | # - Test if they work | ||
162 | # - Save the SDL.sln solution | ||
163 | |||
164 | if(PSP) | ||
165 | # Build EBOOT files if building for PSP | ||
166 | foreach(APP ${SDL_EXAMPLE_EXECUTABLES}) | ||
167 | create_pbp_file( | ||
168 | TARGET ${APP} | ||
169 | TITLE SDL-${APP} | ||
170 | ICON_PATH NULL | ||
171 | BACKGROUND_PATH NULL | ||
172 | PREVIEW_PATH NULL | ||
173 | OUTPUT_DIR $<TARGET_FILE_DIR:${APP}>/sdl-${APP} | ||
174 | ) | ||
175 | endforeach() | ||
176 | endif() | ||
177 | |||
178 | if(N3DS) | ||
179 | set(ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/romfs") | ||
180 | file(MAKE_DIRECTORY "${ROMFS_DIR}") | ||
181 | file(COPY ${RESOURCE_FILES} DESTINATION "${ROMFS_DIR}") | ||
182 | |||
183 | foreach(APP ${SDL_EXAMPLE_EXECUTABLES}) | ||
184 | get_target_property(TARGET_BINARY_DIR ${APP} BINARY_DIR) | ||
185 | set(SMDH_FILE "${TARGET_BINARY_DIR}/${APP}.smdh") | ||
186 | ctr_generate_smdh("${SMDH_FILE}" | ||
187 | NAME "SDL-${APP}" | ||
188 | DESCRIPTION "SDL3 Test suite" | ||
189 | AUTHOR "SDL3 Contributors" | ||
190 | ICON "${CMAKE_CURRENT_SOURCE_DIR}/../test/n3ds/logo48x48.png" | ||
191 | ) | ||
192 | ctr_create_3dsx( | ||
193 | ${APP} | ||
194 | ROMFS "${ROMFS_DIR}" | ||
195 | SMDH "${SMDH_FILE}" | ||
196 | ) | ||
197 | endforeach() | ||
198 | endif() | ||
199 | |||
200 | if(RISCOS) | ||
201 | set(SDL_EXAMPLE_EXECUTABLES_AIF) | ||
202 | foreach(APP ${SDL_EXAMPLE_EXECUTABLES}) | ||
203 | set_property(TARGET ${APP} APPEND_STRING PROPERTY LINK_FLAGS " -static") | ||
204 | add_custom_command( | ||
205 | OUTPUT ${APP},ff8 | ||
206 | COMMAND elf2aif ${APP} ${APP},ff8 | ||
207 | DEPENDS ${APP} | ||
208 | ) | ||
209 | add_custom_target(${APP}-aif ALL DEPENDS ${APP},ff8) | ||
210 | list(APPEND SDL_EXAMPLE_EXECUTABLES_AIF ${CMAKE_CURRENT_BINARY_DIR}/${APP},ff8) | ||
211 | endforeach() | ||
212 | endif() | ||
213 | |||
214 | # Set Apple App ID / Bundle ID. This is needed to launch apps on some Apple | ||
215 | # platforms (iOS, for example). | ||
216 | if(APPLE) | ||
217 | foreach(CURRENT_TARGET ${SDL_EXAMPLE_EXECUTABLES}) | ||
218 | set_target_properties("${CURRENT_TARGET}" PROPERTIES | ||
219 | MACOSX_BUNDLE_GUI_IDENTIFIER "org.libsdl.${CURRENT_TARGET}" | ||
220 | MACOSX_BUNDLE_BUNDLE_VERSION "${SDL3_VERSION}" | ||
221 | MACOSX_BUNDLE_SHORT_VERSION_STRING "${SDL3_VERSION}" | ||
222 | ) | ||
223 | endforeach() | ||
224 | endif() | ||
225 | |||
226 | if(SDL_INSTALL_EXAMPLES) | ||
227 | if(RISCOS) | ||
228 | install( | ||
229 | FILES ${SDL_EXAMPLE_EXECUTABLES_AIF} | ||
230 | DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3 | ||
231 | ) | ||
232 | else() | ||
233 | install( | ||
234 | TARGETS ${SDL_EXAMPLE_EXECUTABLES} | ||
235 | DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3 | ||
236 | ) | ||
237 | endif() | ||
238 | if(MSVC) | ||
239 | foreach(example IN LISTS SDL_EXAMPLE_EXECUTABLES) | ||
240 | SDL_install_pdb(${example} "${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3") | ||
241 | endforeach() | ||
242 | endif() | ||
243 | install( | ||
244 | FILES ${RESOURCE_FILES} | ||
245 | DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-examples/SDL3 | ||
246 | ) | ||
247 | endif() | ||
248 | |||
249 | if(ANDROID AND TARGET SDL3::Jar) | ||
250 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake/android") | ||
251 | find_package(SdlAndroid MODULE) | ||
252 | if(SdlAndroid_FOUND) | ||
253 | set(apks "") | ||
254 | set(packages "") | ||
255 | |||
256 | include(SdlAndroidFunctions) | ||
257 | sdl_create_android_debug_keystore(SDL_example-debug-keystore) | ||
258 | sdl_android_compile_resources(SDL_example-resources RESFOLDER ${CMAKE_CURRENT_SOURCE_DIR}/../test/android/res) | ||
259 | add_custom_target(sdl-example-apks) | ||
260 | foreach(EXAMPLE ${SDL_EXAMPLE_EXECUTABLES}) | ||
261 | set(ANDROID_MANIFEST_APP_NAME "${EXAMPLE}") | ||
262 | set(ANDROID_MANIFEST_LABEL "${EXAMPLE}") | ||
263 | set(ANDROID_MANIFEST_LIB_NAME "$<TARGET_FILE_BASE_NAME:${EXAMPLE}>") | ||
264 | set(ANDROID_MANIFEST_PACKAGE "org.libsdl.sdl.example.${EXAMPLE}") | ||
265 | set(generated_manifest_path "${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-src/AndroidManifest.xml") | ||
266 | string(REPLACE "." "/" JAVA_PACKAGE_DIR "${ANDROID_MANIFEST_PACKAGE}") | ||
267 | set(GENERATED_SRC_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-src") | ||
268 | set(GENERATED_RES_FOLDER "${GENERATED_SRC_FOLDER}/res") | ||
269 | set(JAVA_PACKAGE_DIR "${GENERATED_SRC_FOLDER}/${JAVA_PACKAGE_DIR}") | ||
270 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/SDLEntryTestActivity.java.cmake "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" @ONLY) | ||
271 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/SDLTestActivity.java.cmake "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" @ONLY) | ||
272 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/res/values/strings.xml.cmake android/res/values/strings-${EXAMPLE}.xml @ONLY) | ||
273 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/res/xml/shortcuts.xml.cmake "${GENERATED_RES_FOLDER}/xml/shortcuts.xml" @ONLY) | ||
274 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../test/android/cmake/AndroidManifest.xml.cmake "${generated_manifest_path}" @ONLY) | ||
275 | file(GENERATE | ||
276 | OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-$<CONFIG>/res/values/strings.xml" | ||
277 | INPUT "${CMAKE_CURRENT_BINARY_DIR}/android/res/values/strings-${EXAMPLE}.xml" | ||
278 | ) | ||
279 | |||
280 | sdl_android_compile_resources(${EXAMPLE}-resources | ||
281 | RESOURCES | ||
282 | "${CMAKE_CURRENT_BINARY_DIR}/android/${EXAMPLE}-$<CONFIG>/res/values/strings.xml" | ||
283 | "${GENERATED_RES_FOLDER}/xml/shortcuts.xml" | ||
284 | ) | ||
285 | |||
286 | sdl_android_link_resources(${EXAMPLE}-apk-linked | ||
287 | MANIFEST "${generated_manifest_path}" | ||
288 | PACKAGE ${ANDROID_MANIFEST_PACKAGE} | ||
289 | RES_TARGETS SDL_example-resources ${EXAMPLE}-resources | ||
290 | TARGET_SDK_VERSION 31 | ||
291 | ) | ||
292 | |||
293 | set(CMAKE_JAVA_COMPILE_FLAGS "-encoding;utf-8") | ||
294 | set(classes_path "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${EXAMPLE}-java.dir/classes") | ||
295 | # Some CMake versions have a slow `cmake -E make_directory` implementation | ||
296 | if(NOT IS_DIRECTORY "${classes_path}") | ||
297 | execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${classes_path}") | ||
298 | endif() | ||
299 | set(OUT_JAR "${CMAKE_CURRENT_BINARY_DIR}/${EXAMPLE}.jar") | ||
300 | add_custom_command( | ||
301 | OUTPUT "${OUT_JAR}" | ||
302 | COMMAND ${CMAKE_COMMAND} -E rm -rf "${classes_path}" | ||
303 | COMMAND ${CMAKE_COMMAND} -E make_directory "${classes_path}" | ||
304 | COMMAND ${Java_JAVAC_EXECUTABLE} | ||
305 | -source 1.8 -target 1.8 | ||
306 | -bootclasspath "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>" | ||
307 | "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" | ||
308 | "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" | ||
309 | $<TARGET_PROPERTY:${EXAMPLE}-apk-linked,JAVA_R> | ||
310 | -cp "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>:${SDL_ANDROID_PLATFORM_ANDROID_JAR}" | ||
311 | -d "${classes_path}" | ||
312 | COMMAND ${Java_JAR_EXECUTABLE} cf "${OUT_JAR}" -C "${classes_path}" . | ||
313 | DEPENDS $<TARGET_PROPERTY:${EXAMPLE}-apk-linked,OUTPUTS> "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>" "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" | ||
314 | ) | ||
315 | add_custom_target(${EXAMPLE}-jar DEPENDS "${OUT_JAR}") | ||
316 | set_property(TARGET ${EXAMPLE}-jar PROPERTY OUTPUT "${OUT_JAR}") | ||
317 | |||
318 | set(dexworkdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${EXAMPLE}-dex.dir") | ||
319 | # Some CMake versions have a slow `cmake -E make_directory` implementation | ||
320 | if(NOT IS_DIRECTORY "${dexworkdir}") | ||
321 | execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${dexworkdir}") | ||
322 | endif() | ||
323 | set(classes_dex_base_name "classes.dex") | ||
324 | set(classes_dex "${dexworkdir}/${classes_dex_base_name}") | ||
325 | add_custom_command( | ||
326 | OUTPUT "${classes_dex}" | ||
327 | COMMAND SdlAndroid::d8 | ||
328 | $<TARGET_PROPERTY:${EXAMPLE}-jar,OUTPUT> | ||
329 | $<TARGET_PROPERTY:SDL3::Jar,JAR_FILE> | ||
330 | --lib "${SDL_ANDROID_PLATFORM_ANDROID_JAR}" | ||
331 | --output "${dexworkdir}" | ||
332 | DEPENDS $<TARGET_PROPERTY:${EXAMPLE}-jar,OUTPUT> $<TARGET_PROPERTY:SDL3::Jar,JAR_FILE> | ||
333 | ) | ||
334 | add_custom_target(${EXAMPLE}-dex DEPENDS "${classes_dex}") | ||
335 | set_property(TARGET ${EXAMPLE}-dex PROPERTY OUTPUT "${classes_dex}") | ||
336 | set_property(TARGET ${EXAMPLE}-dex PROPERTY OUTPUT_BASE_NAME "${classes_dex_base_name}") | ||
337 | |||
338 | sdl_add_to_apk_unaligned(${EXAMPLE}-unaligned-apk | ||
339 | APK_IN ${EXAMPLE}-apk-linked | ||
340 | OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/intermediates" | ||
341 | ASSETS ${RESOURCE_FILES} | ||
342 | NATIVE_LIBS SDL3::SDL3-shared ${EXAMPLE} | ||
343 | DEX ${EXAMPLE}-dex | ||
344 | ) | ||
345 | |||
346 | sdl_apk_align(${EXAMPLE}-aligned-apk ${EXAMPLE}-unaligned-apk | ||
347 | OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/intermediates" | ||
348 | ) | ||
349 | sdl_apk_sign(${EXAMPLE}-apk ${EXAMPLE}-aligned-apk | ||
350 | KEYSTORE SDL_example-debug-keystore | ||
351 | ) | ||
352 | add_dependencies(sdl-example-apks ${EXAMPLE}-apk) | ||
353 | |||
354 | if(TARGET SdlAndroid::adb) | ||
355 | add_custom_target(install-${EXAMPLE} | ||
356 | COMMAND "${CMAKE_COMMAND}" -DACTION=install "-DAPKS=$<TARGET_PROPERTY:${EXAMPLE}-apk,OUTPUT>" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake" | ||
357 | DEPENDS "${EXAMPLE}-apk" | ||
358 | ) | ||
359 | add_custom_target(start-${EXAMPLE} | ||
360 | COMMAND "${ADB_BIN}" shell am start-activity -S "${ANDROID_MANIFEST_PACKAGE}/.SDLTestActivity" | ||
361 | ) | ||
362 | add_custom_target(build-install-start-${EXAMPLE} | ||
363 | COMMAND "${CMAKE_COMMAND}" -DACTION=build-install-run "-DEXECUTABLES=${EXAMPLE}" "-DBUILD_FOLDER=${CMAKE_BINARY_DIR}" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake" | ||
364 | ) | ||
365 | endif() | ||
366 | |||
367 | list(APPEND packages "${ANDROID_MANIFEST_PACKAGE}") | ||
368 | list(APPEND install_targets install-${EXAMPLE}) | ||
369 | endforeach() | ||
370 | |||
371 | if(TARGET SdlAndroid::adb) | ||
372 | add_custom_target(install-sdl-example-apks | ||
373 | DEPENDS ${install_targets} | ||
374 | VERBATIM | ||
375 | ) | ||
376 | add_custom_target(uninstall-sdl-example-apks | ||
377 | COMMAND "${CMAKE_COMMAND}" "-DADB=$<TARGET_FILE:SdlAndroid::adb>" -DACTION=uninstall "-DPACKAGES=${packages}" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake" | ||
378 | VERBATIM | ||
379 | ) | ||
380 | endif() | ||
381 | endif() | ||
382 | endif() | ||
diff --git a/src/contrib/SDL-3.2.20/examples/README.md b/src/contrib/SDL-3.2.20/examples/README.md new file mode 100644 index 0000000..872e087 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/README.md | |||
@@ -0,0 +1,67 @@ | |||
1 | # Examples | ||
2 | |||
3 | ## What is this? | ||
4 | |||
5 | In here are a collection of standalone SDL application examples. Unless | ||
6 | otherwise stated, they should work on all supported platforms out of the box. | ||
7 | If they don't [please file a bug to let us know](https://github.com/libsdl-org/SDL/issues/new). | ||
8 | |||
9 | |||
10 | ## What is this SDL_AppIterate thing? | ||
11 | |||
12 | SDL can optionally build apps as a collection of callbacks instead of the | ||
13 | usual program structure that starts and ends in a function called `main`. | ||
14 | The examples use this format for two reasons. | ||
15 | |||
16 | First, it allows the examples to work when built as web applications without | ||
17 | a pile of ugly `#ifdef`s, and all of these examples are published on the web | ||
18 | at [examples.libsdl.org](https://examples.libsdl.org/), so you can easily see | ||
19 | them in action. | ||
20 | |||
21 | Second, it's example code! The callbacks let us cleanly break the program up | ||
22 | into the four logical pieces most apps care about: | ||
23 | |||
24 | - Program startup | ||
25 | - Event handling | ||
26 | - What the program actually does in a single frame | ||
27 | - Program shutdown | ||
28 | |||
29 | A detailed technical explanation of these callbacks is in | ||
30 | docs/README-main-functions.md (or view that page on the web on | ||
31 | [the wiki](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3)). | ||
32 | |||
33 | |||
34 | ## I would like to build and run these examples myself. | ||
35 | |||
36 | When you build SDL with CMake, you can add `-DSDL_EXAMPLES=On` to the | ||
37 | CMake command line. When you build SDL, these examples will be built with it. | ||
38 | |||
39 | But most of these can just be built as a single .c file, as long as you point | ||
40 | your compiler at SDL3's headers and link against SDL. | ||
41 | |||
42 | |||
43 | ## What is the license on the example code? Can I paste this into my project? | ||
44 | |||
45 | All code in the examples directory is considered public domain! You can do | ||
46 | anything you like with it, including copy/paste it into your closed-source | ||
47 | project, sell it, and pretend you wrote it yourself. We do not require you to | ||
48 | give us credit for this code (but we always appreciate if you do!). | ||
49 | |||
50 | This is only true for the examples directory. The rest of SDL falls under the | ||
51 | [zlib license](https://github.com/libsdl-org/SDL/blob/main/LICENSE.txt). | ||
52 | |||
53 | |||
54 | ## What is template.html and highlight-plugin.lua in this directory? | ||
55 | |||
56 | This is what [examples.libsdl.org](https://examples.libsdl.org/) uses when | ||
57 | generating the web versions of these example programs. You can ignore this, | ||
58 | unless you are improving it, in which case we definitely would love to hear | ||
59 | from you! | ||
60 | |||
61 | |||
62 | ## What is template.c in this directory? | ||
63 | |||
64 | If writing new examples, this is the skeleton code we start from, to keep | ||
65 | everything consistent. You can ignore it. | ||
66 | |||
67 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/README.txt b/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/README.txt new file mode 100644 index 0000000..e4283d4 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/README.txt | |||
@@ -0,0 +1,6 @@ | |||
1 | This example code loads a few bitmap files from disk using the asynchronous | ||
2 | i/o, and then draws it to the window. It uses a task group to watch multiple | ||
3 | reads and deal with them in whatever order they finish. | ||
4 | |||
5 | Note that for a single tiny file like this, you'd probably not want to bother | ||
6 | with async i/o in real life, but this is just an example of how to do it. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/load-bitmaps.c b/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/load-bitmaps.c new file mode 100644 index 0000000..44c2abf --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/load-bitmaps.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * This example code loads a bitmap with asynchronous i/o and renders it. | ||
3 | * | ||
4 | * This code is public domain. Feel free to use it for any purpose! | ||
5 | */ | ||
6 | |||
7 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
8 | #include <SDL3/SDL.h> | ||
9 | #include <SDL3/SDL_main.h> | ||
10 | |||
11 | /* We will use this renderer to draw into this window every frame. */ | ||
12 | static SDL_Window *window = NULL; | ||
13 | static SDL_Renderer *renderer = NULL; | ||
14 | static SDL_AsyncIOQueue *queue = NULL; | ||
15 | |||
16 | #define TOTAL_TEXTURES 4 | ||
17 | static const char * const bmps[TOTAL_TEXTURES] = { "sample.bmp", "gamepad_front.bmp", "speaker.bmp", "icon2x.bmp" }; | ||
18 | static SDL_Texture *textures[TOTAL_TEXTURES]; | ||
19 | static const SDL_FRect texture_rects[TOTAL_TEXTURES] = { | ||
20 | { 116, 156, 408, 167 }, | ||
21 | { 20, 200, 96, 60 }, | ||
22 | { 525, 180, 96, 96 }, | ||
23 | { 288, 375, 64, 64 } | ||
24 | }; | ||
25 | |||
26 | /* This function runs once at startup. */ | ||
27 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
28 | { | ||
29 | int i; | ||
30 | |||
31 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
32 | SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL); | ||
33 | return SDL_APP_FAILURE; | ||
34 | } | ||
35 | |||
36 | if (!SDL_CreateWindowAndRenderer("examples/asyncio/load-bitmaps", 640, 480, 0, &window, &renderer)) { | ||
37 | SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL); | ||
38 | return SDL_APP_FAILURE; | ||
39 | } | ||
40 | |||
41 | queue = SDL_CreateAsyncIOQueue(); | ||
42 | if (!queue) { | ||
43 | SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create async i/o queue!", SDL_GetError(), NULL); | ||
44 | return SDL_APP_FAILURE; | ||
45 | } | ||
46 | |||
47 | /* Load some .bmp files asynchronously from wherever the app is being run from, put them in the same queue. */ | ||
48 | for (i = 0; i < SDL_arraysize(bmps); i++) { | ||
49 | char *path = NULL; | ||
50 | SDL_asprintf(&path, "%s%s", SDL_GetBasePath(), bmps[i]); /* allocate a string of the full file path */ | ||
51 | /* you _should) check for failure, but we'll just go on without files here. */ | ||
52 | SDL_LoadFileAsync(path, queue, (void *) bmps[i]); /* attach the filename as app-specific data, so we can see it later. */ | ||
53 | SDL_free(path); | ||
54 | } | ||
55 | |||
56 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
57 | } | ||
58 | |||
59 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
60 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
61 | { | ||
62 | if (event->type == SDL_EVENT_QUIT) { | ||
63 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
64 | } | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs once per frame, and is the heart of the program. */ | ||
70 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
71 | { | ||
72 | SDL_AsyncIOOutcome outcome; | ||
73 | int i; | ||
74 | |||
75 | if (SDL_GetAsyncIOResult(queue, &outcome)) { /* a .bmp file load has finished? */ | ||
76 | if (outcome.result == SDL_ASYNCIO_COMPLETE) { | ||
77 | /* this might be _any_ of the bmps; they might finish loading in any order. */ | ||
78 | for (i = 0; i < SDL_arraysize(bmps); i++) { | ||
79 | /* this doesn't need a strcmp because we gave the pointer from this array to SDL_LoadFileAsync */ | ||
80 | if (outcome.userdata == bmps[i]) { | ||
81 | break; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | if (i < SDL_arraysize(bmps)) { /* (just in case.) */ | ||
86 | SDL_Surface *surface = SDL_LoadBMP_IO(SDL_IOFromConstMem(outcome.buffer, (size_t) outcome.bytes_transferred), true); | ||
87 | if (surface) { /* the renderer is not multithreaded, so create the texture here once the data loads. */ | ||
88 | textures[i] = SDL_CreateTextureFromSurface(renderer, surface); | ||
89 | if (!textures[i]) { | ||
90 | SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create texture!", SDL_GetError(), NULL); | ||
91 | return SDL_APP_FAILURE; | ||
92 | } | ||
93 | SDL_DestroySurface(surface); | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | SDL_free(outcome.buffer); | ||
98 | } | ||
99 | |||
100 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
101 | SDL_RenderClear(renderer); | ||
102 | |||
103 | for (i = 0; i < SDL_arraysize(textures); i++) { | ||
104 | SDL_RenderTexture(renderer, textures[i], NULL, &texture_rects[i]); | ||
105 | } | ||
106 | |||
107 | SDL_RenderPresent(renderer); | ||
108 | |||
109 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
110 | } | ||
111 | |||
112 | /* This function runs once at shutdown. */ | ||
113 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
114 | { | ||
115 | int i; | ||
116 | |||
117 | SDL_DestroyAsyncIOQueue(queue); | ||
118 | |||
119 | for (i = 0; i < SDL_arraysize(textures); i++) { | ||
120 | SDL_DestroyTexture(textures[i]); | ||
121 | } | ||
122 | |||
123 | /* SDL will clean up the window/renderer for us. */ | ||
124 | } | ||
125 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/thumbnail.png b/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/thumbnail.png new file mode 100644 index 0000000..4f8be2a --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/asyncio/01-load-bitmaps/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/asyncio/description.txt b/src/contrib/SDL-3.2.20/examples/asyncio/description.txt new file mode 100644 index 0000000..c3aafe1 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/asyncio/description.txt | |||
@@ -0,0 +1 @@ | |||
Asynchronous I/O \ No newline at end of file | |||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/01-simple-playback/README.txt b/src/contrib/SDL-3.2.20/examples/audio/01-simple-playback/README.txt new file mode 100644 index 0000000..20ad059 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/01-simple-playback/README.txt | |||
@@ -0,0 +1,5 @@ | |||
1 | If you're running this in a web browser, you need to click the window before you'll hear anything! | ||
2 | |||
3 | This example code creates a simple audio stream for playing sound, and | ||
4 | generates a sine wave sound effect for it to play as time goes on. This is the | ||
5 | simplest way to get up and running with procedural sound. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/01-simple-playback/simple-playback.c b/src/contrib/SDL-3.2.20/examples/audio/01-simple-playback/simple-playback.c new file mode 100644 index 0000000..15126e5 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/01-simple-playback/simple-playback.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * This example code creates a simple audio stream for playing sound, and | ||
3 | * generates a sine wave sound effect for it to play as time goes on. This | ||
4 | * is the simplest way to get up and running with procedural sound. | ||
5 | * | ||
6 | * This code is public domain. Feel free to use it for any purpose! | ||
7 | */ | ||
8 | |||
9 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
10 | #include <SDL3/SDL.h> | ||
11 | #include <SDL3/SDL_main.h> | ||
12 | |||
13 | /* We will use this renderer to draw into this window every frame. */ | ||
14 | static SDL_Window *window = NULL; | ||
15 | static SDL_Renderer *renderer = NULL; | ||
16 | static SDL_AudioStream *stream = NULL; | ||
17 | static int current_sine_sample = 0; | ||
18 | |||
19 | /* This function runs once at startup. */ | ||
20 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
21 | { | ||
22 | SDL_AudioSpec spec; | ||
23 | |||
24 | SDL_SetAppMetadata("Example Audio Simple Playback", "1.0", "com.example.audio-simple-playback"); | ||
25 | |||
26 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { | ||
27 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
28 | return SDL_APP_FAILURE; | ||
29 | } | ||
30 | |||
31 | /* we don't _need_ a window for audio-only things but it's good policy to have one. */ | ||
32 | if (!SDL_CreateWindowAndRenderer("examples/audio/simple-playback", 640, 480, 0, &window, &renderer)) { | ||
33 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
34 | return SDL_APP_FAILURE; | ||
35 | } | ||
36 | |||
37 | /* We're just playing a single thing here, so we'll use the simplified option. | ||
38 | We are always going to feed audio in as mono, float32 data at 8000Hz. | ||
39 | The stream will convert it to whatever the hardware wants on the other side. */ | ||
40 | spec.channels = 1; | ||
41 | spec.format = SDL_AUDIO_F32; | ||
42 | spec.freq = 8000; | ||
43 | stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL); | ||
44 | if (!stream) { | ||
45 | SDL_Log("Couldn't create audio stream: %s", SDL_GetError()); | ||
46 | return SDL_APP_FAILURE; | ||
47 | } | ||
48 | |||
49 | /* SDL_OpenAudioDeviceStream starts the device paused. You have to tell it to start! */ | ||
50 | SDL_ResumeAudioStreamDevice(stream); | ||
51 | |||
52 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
53 | } | ||
54 | |||
55 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
56 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
57 | { | ||
58 | if (event->type == SDL_EVENT_QUIT) { | ||
59 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
60 | } | ||
61 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
62 | } | ||
63 | |||
64 | /* This function runs once per frame, and is the heart of the program. */ | ||
65 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
66 | { | ||
67 | /* see if we need to feed the audio stream more data yet. | ||
68 | We're being lazy here, but if there's less than half a second queued, generate more. | ||
69 | A sine wave is unchanging audio--easy to stream--but for video games, you'll want | ||
70 | to generate significantly _less_ audio ahead of time! */ | ||
71 | const int minimum_audio = (8000 * sizeof (float)) / 2; /* 8000 float samples per second. Half of that. */ | ||
72 | if (SDL_GetAudioStreamQueued(stream) < minimum_audio) { | ||
73 | static float samples[512]; /* this will feed 512 samples each frame until we get to our maximum. */ | ||
74 | int i; | ||
75 | |||
76 | /* generate a 440Hz pure tone */ | ||
77 | for (i = 0; i < SDL_arraysize(samples); i++) { | ||
78 | const int freq = 440; | ||
79 | const float phase = current_sine_sample * freq / 8000.0f; | ||
80 | samples[i] = SDL_sinf(phase * 2 * SDL_PI_F); | ||
81 | current_sine_sample++; | ||
82 | } | ||
83 | |||
84 | /* wrapping around to avoid floating-point errors */ | ||
85 | current_sine_sample %= 8000; | ||
86 | |||
87 | /* feed the new data to the stream. It will queue at the end, and trickle out as the hardware needs more data. */ | ||
88 | SDL_PutAudioStreamData(stream, samples, sizeof (samples)); | ||
89 | } | ||
90 | |||
91 | /* we're not doing anything with the renderer, so just blank it out. */ | ||
92 | SDL_RenderClear(renderer); | ||
93 | SDL_RenderPresent(renderer); | ||
94 | |||
95 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
96 | } | ||
97 | |||
98 | /* This function runs once at shutdown. */ | ||
99 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
100 | { | ||
101 | /* SDL will clean up the window/renderer for us. */ | ||
102 | } | ||
103 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/02-simple-playback-callback/README.txt b/src/contrib/SDL-3.2.20/examples/audio/02-simple-playback-callback/README.txt new file mode 100644 index 0000000..888ae34 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/02-simple-playback-callback/README.txt | |||
@@ -0,0 +1,5 @@ | |||
1 | If you're running this in a web browser, you need to click the window before you'll hear anything! | ||
2 | |||
3 | This example code creates a simple audio stream for playing sound, and | ||
4 | generates a sine wave sound effect for it to play as time goes on. Unlike | ||
5 | the previous example, this uses a callback to generate sound. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/02-simple-playback-callback/simple-playback-callback.c b/src/contrib/SDL-3.2.20/examples/audio/02-simple-playback-callback/simple-playback-callback.c new file mode 100644 index 0000000..c011c72 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/02-simple-playback-callback/simple-playback-callback.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * This example code creates a simple audio stream for playing sound, and | ||
3 | * generates a sine wave sound effect for it to play as time goes on. Unlike | ||
4 | * the previous example, this uses a callback to generate sound. | ||
5 | * | ||
6 | * This might be the path of least resistance if you're moving an SDL2 | ||
7 | * program's audio code to SDL3. | ||
8 | * | ||
9 | * This code is public domain. Feel free to use it for any purpose! | ||
10 | */ | ||
11 | |||
12 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
13 | #include <SDL3/SDL.h> | ||
14 | #include <SDL3/SDL_main.h> | ||
15 | |||
16 | /* We will use this renderer to draw into this window every frame. */ | ||
17 | static SDL_Window *window = NULL; | ||
18 | static SDL_Renderer *renderer = NULL; | ||
19 | static SDL_AudioStream *stream = NULL; | ||
20 | static int current_sine_sample = 0; | ||
21 | |||
22 | /* this function will be called (usually in a background thread) when the audio stream is consuming data. */ | ||
23 | static void SDLCALL FeedTheAudioStreamMore(void *userdata, SDL_AudioStream *astream, int additional_amount, int total_amount) | ||
24 | { | ||
25 | /* total_amount is how much data the audio stream is eating right now, additional_amount is how much more it needs | ||
26 | than what it currently has queued (which might be zero!). You can supply any amount of data here; it will take what | ||
27 | it needs and use the extra later. If you don't give it enough, it will take everything and then feed silence to the | ||
28 | hardware for the rest. Ideally, though, we always give it what it needs and no extra, so we aren't buffering more | ||
29 | than necessary. */ | ||
30 | additional_amount /= sizeof (float); /* convert from bytes to samples */ | ||
31 | while (additional_amount > 0) { | ||
32 | float samples[128]; /* this will feed 128 samples each iteration until we have enough. */ | ||
33 | const int total = SDL_min(additional_amount, SDL_arraysize(samples)); | ||
34 | int i; | ||
35 | |||
36 | /* generate a 440Hz pure tone */ | ||
37 | for (i = 0; i < total; i++) { | ||
38 | const int freq = 440; | ||
39 | const float phase = current_sine_sample * freq / 8000.0f; | ||
40 | samples[i] = SDL_sinf(phase * 2 * SDL_PI_F); | ||
41 | current_sine_sample++; | ||
42 | } | ||
43 | |||
44 | /* wrapping around to avoid floating-point errors */ | ||
45 | current_sine_sample %= 8000; | ||
46 | |||
47 | /* feed the new data to the stream. It will queue at the end, and trickle out as the hardware needs more data. */ | ||
48 | SDL_PutAudioStreamData(astream, samples, total * sizeof (float)); | ||
49 | additional_amount -= total; /* subtract what we've just fed the stream. */ | ||
50 | } | ||
51 | } | ||
52 | |||
53 | /* This function runs once at startup. */ | ||
54 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
55 | { | ||
56 | SDL_AudioSpec spec; | ||
57 | |||
58 | SDL_SetAppMetadata("Example Simple Audio Playback Callback", "1.0", "com.example.audio-simple-playback-callback"); | ||
59 | |||
60 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { | ||
61 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
62 | return SDL_APP_FAILURE; | ||
63 | } | ||
64 | |||
65 | /* we don't _need_ a window for audio-only things but it's good policy to have one. */ | ||
66 | if (!SDL_CreateWindowAndRenderer("examples/audio/simple-playback-callback", 640, 480, 0, &window, &renderer)) { | ||
67 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
68 | return SDL_APP_FAILURE; | ||
69 | } | ||
70 | |||
71 | /* We're just playing a single thing here, so we'll use the simplified option. | ||
72 | We are always going to feed audio in as mono, float32 data at 8000Hz. | ||
73 | The stream will convert it to whatever the hardware wants on the other side. */ | ||
74 | spec.channels = 1; | ||
75 | spec.format = SDL_AUDIO_F32; | ||
76 | spec.freq = 8000; | ||
77 | stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, FeedTheAudioStreamMore, NULL); | ||
78 | if (!stream) { | ||
79 | SDL_Log("Couldn't create audio stream: %s", SDL_GetError()); | ||
80 | return SDL_APP_FAILURE; | ||
81 | } | ||
82 | |||
83 | /* SDL_OpenAudioDeviceStream starts the device paused. You have to tell it to start! */ | ||
84 | SDL_ResumeAudioStreamDevice(stream); | ||
85 | |||
86 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
87 | } | ||
88 | |||
89 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
90 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
91 | { | ||
92 | if (event->type == SDL_EVENT_QUIT) { | ||
93 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
94 | } | ||
95 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
96 | } | ||
97 | |||
98 | /* This function runs once per frame, and is the heart of the program. */ | ||
99 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
100 | { | ||
101 | /* we're not doing anything with the renderer, so just blank it out. */ | ||
102 | SDL_RenderClear(renderer); | ||
103 | SDL_RenderPresent(renderer); | ||
104 | |||
105 | /* all the work of feeding the audio stream is happening in a callback in a background thread. */ | ||
106 | |||
107 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
108 | } | ||
109 | |||
110 | /* This function runs once at shutdown. */ | ||
111 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
112 | { | ||
113 | /* SDL will clean up the window/renderer for us. */ | ||
114 | } | ||
115 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/03-load-wav/README.txt b/src/contrib/SDL-3.2.20/examples/audio/03-load-wav/README.txt new file mode 100644 index 0000000..57eb90c --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/03-load-wav/README.txt | |||
@@ -0,0 +1,5 @@ | |||
1 | If you're running this in a web browser, you need to click the window before you'll hear anything! | ||
2 | |||
3 | This example code creates a simple audio stream for playing sound, and | ||
4 | loads a .wav file that is pushed through the stream in a loop. | ||
5 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/03-load-wav/load-wav.c b/src/contrib/SDL-3.2.20/examples/audio/03-load-wav/load-wav.c new file mode 100644 index 0000000..c517e5d --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/03-load-wav/load-wav.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * This example code creates a simple audio stream for playing sound, and | ||
3 | * loads a .wav file that is pushed through the stream in a loop. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | * | ||
7 | * The .wav file is a sample from Will Provost's song, The Living Proof, | ||
8 | * used with permission. | ||
9 | * | ||
10 | * From the album The Living Proof | ||
11 | * Publisher: 5 Guys Named Will | ||
12 | * Copyright 1996 Will Provost | ||
13 | * https://itunes.apple.com/us/album/the-living-proof/id4153978 | ||
14 | * http://www.amazon.com/The-Living-Proof-Will-Provost/dp/B00004R8RH | ||
15 | */ | ||
16 | |||
17 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
18 | #include <SDL3/SDL.h> | ||
19 | #include <SDL3/SDL_main.h> | ||
20 | |||
21 | /* We will use this renderer to draw into this window every frame. */ | ||
22 | static SDL_Window *window = NULL; | ||
23 | static SDL_Renderer *renderer = NULL; | ||
24 | static SDL_AudioStream *stream = NULL; | ||
25 | static Uint8 *wav_data = NULL; | ||
26 | static Uint32 wav_data_len = 0; | ||
27 | |||
28 | /* This function runs once at startup. */ | ||
29 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
30 | { | ||
31 | SDL_AudioSpec spec; | ||
32 | char *wav_path = NULL; | ||
33 | |||
34 | SDL_SetAppMetadata("Example Audio Load Wave", "1.0", "com.example.audio-load-wav"); | ||
35 | |||
36 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { | ||
37 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
38 | return SDL_APP_FAILURE; | ||
39 | } | ||
40 | |||
41 | /* we don't _need_ a window for audio-only things but it's good policy to have one. */ | ||
42 | if (!SDL_CreateWindowAndRenderer("examples/audio/load-wav", 640, 480, 0, &window, &renderer)) { | ||
43 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
44 | return SDL_APP_FAILURE; | ||
45 | } | ||
46 | |||
47 | /* Load the .wav file from wherever the app is being run from. */ | ||
48 | SDL_asprintf(&wav_path, "%ssample.wav", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
49 | if (!SDL_LoadWAV(wav_path, &spec, &wav_data, &wav_data_len)) { | ||
50 | SDL_Log("Couldn't load .wav file: %s", SDL_GetError()); | ||
51 | return SDL_APP_FAILURE; | ||
52 | } | ||
53 | |||
54 | SDL_free(wav_path); /* done with this string. */ | ||
55 | |||
56 | /* Create our audio stream in the same format as the .wav file. It'll convert to what the audio hardware wants. */ | ||
57 | stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL); | ||
58 | if (!stream) { | ||
59 | SDL_Log("Couldn't create audio stream: %s", SDL_GetError()); | ||
60 | return SDL_APP_FAILURE; | ||
61 | } | ||
62 | |||
63 | /* SDL_OpenAudioDeviceStream starts the device paused. You have to tell it to start! */ | ||
64 | SDL_ResumeAudioStreamDevice(stream); | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
70 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
71 | { | ||
72 | if (event->type == SDL_EVENT_QUIT) { | ||
73 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
74 | } | ||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs once per frame, and is the heart of the program. */ | ||
79 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
80 | { | ||
81 | /* see if we need to feed the audio stream more data yet. | ||
82 | We're being lazy here, but if there's less than the entire wav file left to play, | ||
83 | just shove a whole copy of it into the queue, so we always have _tons_ of | ||
84 | data queued for playback. */ | ||
85 | if (SDL_GetAudioStreamQueued(stream) < (int)wav_data_len) { | ||
86 | /* feed more data to the stream. It will queue at the end, and trickle out as the hardware needs more data. */ | ||
87 | SDL_PutAudioStreamData(stream, wav_data, wav_data_len); | ||
88 | } | ||
89 | |||
90 | /* we're not doing anything with the renderer, so just blank it out. */ | ||
91 | SDL_RenderClear(renderer); | ||
92 | SDL_RenderPresent(renderer); | ||
93 | |||
94 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
95 | } | ||
96 | |||
97 | /* This function runs once at shutdown. */ | ||
98 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
99 | { | ||
100 | SDL_free(wav_data); /* strictly speaking, this isn't necessary because the process is ending, but it's good policy. */ | ||
101 | /* SDL will clean up the window/renderer for us. */ | ||
102 | } | ||
103 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/04-multiple-streams/README.txt b/src/contrib/SDL-3.2.20/examples/audio/04-multiple-streams/README.txt new file mode 100644 index 0000000..9ef2275 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/04-multiple-streams/README.txt | |||
@@ -0,0 +1,5 @@ | |||
1 | If you're running this in a web browser, you need to click the window before you'll hear anything! | ||
2 | |||
3 | This example code loads two .wav files, puts them an audio streams and binds | ||
4 | them for playback, repeating both sounds on loop. This shows several streams | ||
5 | mixing into a single playback device. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/04-multiple-streams/multiple-streams.c b/src/contrib/SDL-3.2.20/examples/audio/04-multiple-streams/multiple-streams.c new file mode 100644 index 0000000..8d3bfaa --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/04-multiple-streams/multiple-streams.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * This example code loads two .wav files, puts them an audio streams and | ||
3 | * binds them for playback, repeating both sounds on loop. This shows several | ||
4 | * streams mixing into a single playback device. | ||
5 | * | ||
6 | * This code is public domain. Feel free to use it for any purpose! | ||
7 | */ | ||
8 | |||
9 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
10 | #include <SDL3/SDL.h> | ||
11 | #include <SDL3/SDL_main.h> | ||
12 | |||
13 | /* We will use this renderer to draw into this window every frame. */ | ||
14 | static SDL_Window *window = NULL; | ||
15 | static SDL_Renderer *renderer = NULL; | ||
16 | static SDL_AudioDeviceID audio_device = 0; | ||
17 | |||
18 | /* things that are playing sound (the audiostream itself, plus the original data, so we can refill to loop. */ | ||
19 | typedef struct Sound { | ||
20 | Uint8 *wav_data; | ||
21 | Uint32 wav_data_len; | ||
22 | SDL_AudioStream *stream; | ||
23 | } Sound; | ||
24 | |||
25 | static Sound sounds[2]; | ||
26 | |||
27 | static bool init_sound(const char *fname, Sound *sound) | ||
28 | { | ||
29 | bool retval = false; | ||
30 | SDL_AudioSpec spec; | ||
31 | char *wav_path = NULL; | ||
32 | |||
33 | /* Load the .wav files from wherever the app is being run from. */ | ||
34 | SDL_asprintf(&wav_path, "%s%s", SDL_GetBasePath(), fname); /* allocate a string of the full file path */ | ||
35 | if (!SDL_LoadWAV(wav_path, &spec, &sound->wav_data, &sound->wav_data_len)) { | ||
36 | SDL_Log("Couldn't load .wav file: %s", SDL_GetError()); | ||
37 | return false; | ||
38 | } | ||
39 | |||
40 | /* Create an audio stream. Set the source format to the wav's format (what | ||
41 | we'll input), leave the dest format NULL here (it'll change to what the | ||
42 | device wants once we bind it). */ | ||
43 | sound->stream = SDL_CreateAudioStream(&spec, NULL); | ||
44 | if (!sound->stream) { | ||
45 | SDL_Log("Couldn't create audio stream: %s", SDL_GetError()); | ||
46 | } else if (!SDL_BindAudioStream(audio_device, sound->stream)) { /* once bound, it'll start playing when there is data available! */ | ||
47 | SDL_Log("Failed to bind '%s' stream to device: %s", fname, SDL_GetError()); | ||
48 | } else { | ||
49 | retval = true; /* success! */ | ||
50 | } | ||
51 | |||
52 | SDL_free(wav_path); /* done with this string. */ | ||
53 | return retval; | ||
54 | } | ||
55 | |||
56 | |||
57 | /* This function runs once at startup. */ | ||
58 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
59 | { | ||
60 | |||
61 | SDL_SetAppMetadata("Example Audio Multiple Streams", "1.0", "com.example.audio-multiple-streams"); | ||
62 | |||
63 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { | ||
64 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
65 | return SDL_APP_FAILURE; | ||
66 | } | ||
67 | |||
68 | if (!SDL_CreateWindowAndRenderer("examples/audio/multiple-streams", 640, 480, 0, &window, &renderer)) { | ||
69 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
70 | return SDL_APP_FAILURE; | ||
71 | } | ||
72 | |||
73 | /* open the default audio device in whatever format it prefers; our audio streams will adjust to it. */ | ||
74 | audio_device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL); | ||
75 | if (audio_device == 0) { | ||
76 | SDL_Log("Couldn't open audio device: %s", SDL_GetError()); | ||
77 | return SDL_APP_FAILURE; | ||
78 | } | ||
79 | |||
80 | if (!init_sound("sample.wav", &sounds[0])) { | ||
81 | return SDL_APP_FAILURE; | ||
82 | } else if (!init_sound("sword.wav", &sounds[1])) { | ||
83 | return SDL_APP_FAILURE; | ||
84 | } | ||
85 | |||
86 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
87 | } | ||
88 | |||
89 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
90 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
91 | { | ||
92 | if (event->type == SDL_EVENT_QUIT) { | ||
93 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
94 | } | ||
95 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
96 | } | ||
97 | |||
98 | /* This function runs once per frame, and is the heart of the program. */ | ||
99 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
100 | { | ||
101 | int i; | ||
102 | |||
103 | for (i = 0; i < SDL_arraysize(sounds); i++) { | ||
104 | /* If less than a full copy of the audio is queued for playback, put another copy in there. | ||
105 | This is overkill, but easy when lots of RAM is cheap. One could be more careful and | ||
106 | queue less at a time, as long as the stream doesn't run dry. */ | ||
107 | if (SDL_GetAudioStreamQueued(sounds[i].stream) < ((int) sounds[i].wav_data_len)) { | ||
108 | SDL_PutAudioStreamData(sounds[i].stream, sounds[i].wav_data, (int) sounds[i].wav_data_len); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | /* just blank the screen. */ | ||
113 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
114 | SDL_RenderClear(renderer); | ||
115 | SDL_RenderPresent(renderer); | ||
116 | |||
117 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
118 | } | ||
119 | |||
120 | /* This function runs once at shutdown. */ | ||
121 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
122 | { | ||
123 | int i; | ||
124 | |||
125 | SDL_CloseAudioDevice(audio_device); | ||
126 | |||
127 | for (i = 0; i < SDL_arraysize(sounds); i++) { | ||
128 | if (sounds[i].stream) { | ||
129 | SDL_DestroyAudioStream(sounds[i].stream); | ||
130 | } | ||
131 | SDL_free(sounds[i].wav_data); | ||
132 | } | ||
133 | |||
134 | /* SDL will clean up the window/renderer for us. */ | ||
135 | } | ||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/audio/onmouseover.webp new file mode 100644 index 0000000..1f3ba4b --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/audio/thumbnail.png b/src/contrib/SDL-3.2.20/examples/audio/thumbnail.png new file mode 100644 index 0000000..10bc6c8 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/audio/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/README.txt b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/README.txt new file mode 100644 index 0000000..f7ac1f5 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/README.txt | |||
@@ -0,0 +1 @@ | |||
This reads from a webcam and draws frames of video to the screen. | |||
diff --git a/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/onmouseover.webp new file mode 100644 index 0000000..1d414e6 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/read-and-draw.c b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/read-and-draw.c new file mode 100644 index 0000000..989fd54 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/read-and-draw.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * This example code reads frames from a camera and draws it to the screen. | ||
3 | * | ||
4 | * This is a very simple approach that is often Good Enough. You can get | ||
5 | * fancier with this: multiple cameras, front/back facing cameras on phones, | ||
6 | * color spaces, choosing formats and framerates...this just requests | ||
7 | * _anything_ and goes with what it is handed. | ||
8 | * | ||
9 | * This code is public domain. Feel free to use it for any purpose! | ||
10 | */ | ||
11 | |||
12 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
13 | #include <SDL3/SDL.h> | ||
14 | #include <SDL3/SDL_main.h> | ||
15 | |||
16 | /* We will use this renderer to draw into this window every frame. */ | ||
17 | static SDL_Window *window = NULL; | ||
18 | static SDL_Renderer *renderer = NULL; | ||
19 | static SDL_Camera *camera = NULL; | ||
20 | static SDL_Texture *texture = NULL; | ||
21 | |||
22 | |||
23 | /* This function runs once at startup. */ | ||
24 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
25 | { | ||
26 | SDL_CameraID *devices = NULL; | ||
27 | int devcount = 0; | ||
28 | |||
29 | SDL_SetAppMetadata("Example Camera Read and Draw", "1.0", "com.example.camera-read-and-draw"); | ||
30 | |||
31 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CAMERA)) { | ||
32 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
33 | return SDL_APP_FAILURE; | ||
34 | } | ||
35 | |||
36 | if (!SDL_CreateWindowAndRenderer("examples/camera/read-and-draw", 640, 480, 0, &window, &renderer)) { | ||
37 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
38 | return SDL_APP_FAILURE; | ||
39 | } | ||
40 | |||
41 | devices = SDL_GetCameras(&devcount); | ||
42 | if (devices == NULL) { | ||
43 | SDL_Log("Couldn't enumerate camera devices: %s", SDL_GetError()); | ||
44 | return SDL_APP_FAILURE; | ||
45 | } else if (devcount == 0) { | ||
46 | SDL_Log("Couldn't find any camera devices! Please connect a camera and try again."); | ||
47 | return SDL_APP_FAILURE; | ||
48 | } | ||
49 | |||
50 | camera = SDL_OpenCamera(devices[0], NULL); // just take the first thing we see in any format it wants. | ||
51 | SDL_free(devices); | ||
52 | if (camera == NULL) { | ||
53 | SDL_Log("Couldn't open camera: %s", SDL_GetError()); | ||
54 | return SDL_APP_FAILURE; | ||
55 | } | ||
56 | |||
57 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
58 | } | ||
59 | |||
60 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
61 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
62 | { | ||
63 | if (event->type == SDL_EVENT_QUIT) { | ||
64 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
65 | } else if (event->type == SDL_EVENT_CAMERA_DEVICE_APPROVED) { | ||
66 | SDL_Log("Camera use approved by user!"); | ||
67 | } else if (event->type == SDL_EVENT_CAMERA_DEVICE_DENIED) { | ||
68 | SDL_Log("Camera use denied by user!"); | ||
69 | return SDL_APP_FAILURE; | ||
70 | } | ||
71 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
72 | } | ||
73 | |||
74 | /* This function runs once per frame, and is the heart of the program. */ | ||
75 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
76 | { | ||
77 | Uint64 timestampNS = 0; | ||
78 | SDL_Surface *frame = SDL_AcquireCameraFrame(camera, ×tampNS); | ||
79 | |||
80 | if (frame != NULL) { | ||
81 | /* Some platforms (like Emscripten) don't know _what_ the camera offers | ||
82 | until the user gives permission, so we build the texture and resize | ||
83 | the window when we get a first frame from the camera. */ | ||
84 | if (!texture) { | ||
85 | SDL_SetWindowSize(window, frame->w, frame->h); /* Resize the window to match */ | ||
86 | texture = SDL_CreateTexture(renderer, frame->format, SDL_TEXTUREACCESS_STREAMING, frame->w, frame->h); | ||
87 | } | ||
88 | |||
89 | if (texture) { | ||
90 | SDL_UpdateTexture(texture, NULL, frame->pixels, frame->pitch); | ||
91 | } | ||
92 | |||
93 | SDL_ReleaseCameraFrame(camera, frame); | ||
94 | } | ||
95 | |||
96 | SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, SDL_ALPHA_OPAQUE); | ||
97 | SDL_RenderClear(renderer); | ||
98 | if (texture) { /* draw the latest camera frame, if available. */ | ||
99 | SDL_RenderTexture(renderer, texture, NULL, NULL); | ||
100 | } | ||
101 | SDL_RenderPresent(renderer); | ||
102 | |||
103 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
104 | } | ||
105 | |||
106 | /* This function runs once at shutdown. */ | ||
107 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
108 | { | ||
109 | SDL_CloseCamera(camera); | ||
110 | SDL_DestroyTexture(texture); | ||
111 | /* SDL will clean up the window/renderer for us. */ | ||
112 | } | ||
113 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/thumbnail.png b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/thumbnail.png new file mode 100644 index 0000000..98fe4e0 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/camera/01-read-and-draw/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/categories.txt b/src/contrib/SDL-3.2.20/examples/categories.txt new file mode 100644 index 0000000..8a9b5ec --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/categories.txt | |||
@@ -0,0 +1,13 @@ | |||
1 | # Blank lines and lines that start with '#' in this file are ignored. | ||
2 | |||
3 | # Categories, by directory name, go in here, in the order they should be | ||
4 | # listed on the main page. If this file is missing, it'll assume any | ||
5 | # subdirectory is a category and sort them alphabetically. | ||
6 | |||
7 | renderer | ||
8 | input | ||
9 | audio | ||
10 | camera | ||
11 | asyncio | ||
12 | pen | ||
13 | demo | ||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/01-snake/README.txt b/src/contrib/SDL-3.2.20/examples/demo/01-snake/README.txt new file mode 100644 index 0000000..1cf9784 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/01-snake/README.txt | |||
@@ -0,0 +1 @@ | |||
A complete game of Snake, written in SDL. | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/01-snake/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/demo/01-snake/onmouseover.webp new file mode 100644 index 0000000..1757202 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/01-snake/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/01-snake/snake.c b/src/contrib/SDL-3.2.20/examples/demo/01-snake/snake.c new file mode 100644 index 0000000..0aca862 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/01-snake/snake.c | |||
@@ -0,0 +1,350 @@ | |||
1 | /* | ||
2 | * Logic implementation of the Snake game. It is designed to efficiently | ||
3 | * represent the state of the game in memory. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | #define STEP_RATE_IN_MILLISECONDS 125 | ||
13 | #define SNAKE_BLOCK_SIZE_IN_PIXELS 24 | ||
14 | #define SDL_WINDOW_WIDTH (SNAKE_BLOCK_SIZE_IN_PIXELS * SNAKE_GAME_WIDTH) | ||
15 | #define SDL_WINDOW_HEIGHT (SNAKE_BLOCK_SIZE_IN_PIXELS * SNAKE_GAME_HEIGHT) | ||
16 | |||
17 | #define SNAKE_GAME_WIDTH 24U | ||
18 | #define SNAKE_GAME_HEIGHT 18U | ||
19 | #define SNAKE_MATRIX_SIZE (SNAKE_GAME_WIDTH * SNAKE_GAME_HEIGHT) | ||
20 | |||
21 | #define THREE_BITS 0x7U /* ~CHAR_MAX >> (CHAR_BIT - SNAKE_CELL_MAX_BITS) */ | ||
22 | #define SHIFT(x, y) (((x) + ((y) * SNAKE_GAME_WIDTH)) * SNAKE_CELL_MAX_BITS) | ||
23 | |||
24 | typedef enum | ||
25 | { | ||
26 | SNAKE_CELL_NOTHING = 0U, | ||
27 | SNAKE_CELL_SRIGHT = 1U, | ||
28 | SNAKE_CELL_SUP = 2U, | ||
29 | SNAKE_CELL_SLEFT = 3U, | ||
30 | SNAKE_CELL_SDOWN = 4U, | ||
31 | SNAKE_CELL_FOOD = 5U | ||
32 | } SnakeCell; | ||
33 | |||
34 | #define SNAKE_CELL_MAX_BITS 3U /* floor(log2(SNAKE_CELL_FOOD)) + 1 */ | ||
35 | |||
36 | typedef enum | ||
37 | { | ||
38 | SNAKE_DIR_RIGHT, | ||
39 | SNAKE_DIR_UP, | ||
40 | SNAKE_DIR_LEFT, | ||
41 | SNAKE_DIR_DOWN | ||
42 | } SnakeDirection; | ||
43 | |||
44 | typedef struct | ||
45 | { | ||
46 | unsigned char cells[(SNAKE_MATRIX_SIZE * SNAKE_CELL_MAX_BITS) / 8U]; | ||
47 | char head_xpos; | ||
48 | char head_ypos; | ||
49 | char tail_xpos; | ||
50 | char tail_ypos; | ||
51 | char next_dir; | ||
52 | char inhibit_tail_step; | ||
53 | unsigned occupied_cells; | ||
54 | } SnakeContext; | ||
55 | |||
56 | typedef struct | ||
57 | { | ||
58 | SDL_Window *window; | ||
59 | SDL_Renderer *renderer; | ||
60 | SnakeContext snake_ctx; | ||
61 | Uint64 last_step; | ||
62 | } AppState; | ||
63 | |||
64 | SnakeCell snake_cell_at(const SnakeContext *ctx, char x, char y) | ||
65 | { | ||
66 | const int shift = SHIFT(x, y); | ||
67 | unsigned short range; | ||
68 | SDL_memcpy(&range, ctx->cells + (shift / 8), sizeof(range)); | ||
69 | return (SnakeCell)((range >> (shift % 8)) & THREE_BITS); | ||
70 | } | ||
71 | |||
72 | static void set_rect_xy_(SDL_FRect *r, short x, short y) | ||
73 | { | ||
74 | r->x = (float)(x * SNAKE_BLOCK_SIZE_IN_PIXELS); | ||
75 | r->y = (float)(y * SNAKE_BLOCK_SIZE_IN_PIXELS); | ||
76 | } | ||
77 | |||
78 | static void put_cell_at_(SnakeContext *ctx, char x, char y, SnakeCell ct) | ||
79 | { | ||
80 | const int shift = SHIFT(x, y); | ||
81 | const int adjust = shift % 8; | ||
82 | unsigned char *const pos = ctx->cells + (shift / 8); | ||
83 | unsigned short range; | ||
84 | SDL_memcpy(&range, pos, sizeof(range)); | ||
85 | range &= ~(THREE_BITS << adjust); /* clear bits */ | ||
86 | range |= (ct & THREE_BITS) << adjust; | ||
87 | SDL_memcpy(pos, &range, sizeof(range)); | ||
88 | } | ||
89 | |||
90 | static int are_cells_full_(SnakeContext *ctx) | ||
91 | { | ||
92 | return ctx->occupied_cells == SNAKE_GAME_WIDTH * SNAKE_GAME_HEIGHT; | ||
93 | } | ||
94 | |||
95 | static void new_food_pos_(SnakeContext *ctx) | ||
96 | { | ||
97 | while (true) { | ||
98 | const char x = (char) SDL_rand(SNAKE_GAME_WIDTH); | ||
99 | const char y = (char) SDL_rand(SNAKE_GAME_HEIGHT); | ||
100 | if (snake_cell_at(ctx, x, y) == SNAKE_CELL_NOTHING) { | ||
101 | put_cell_at_(ctx, x, y, SNAKE_CELL_FOOD); | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | |||
107 | void snake_initialize(SnakeContext *ctx) | ||
108 | { | ||
109 | int i; | ||
110 | SDL_zeroa(ctx->cells); | ||
111 | ctx->head_xpos = ctx->tail_xpos = SNAKE_GAME_WIDTH / 2; | ||
112 | ctx->head_ypos = ctx->tail_ypos = SNAKE_GAME_HEIGHT / 2; | ||
113 | ctx->next_dir = SNAKE_DIR_RIGHT; | ||
114 | ctx->inhibit_tail_step = ctx->occupied_cells = 4; | ||
115 | --ctx->occupied_cells; | ||
116 | put_cell_at_(ctx, ctx->tail_xpos, ctx->tail_ypos, SNAKE_CELL_SRIGHT); | ||
117 | for (i = 0; i < 4; i++) { | ||
118 | new_food_pos_(ctx); | ||
119 | ++ctx->occupied_cells; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | void snake_redir(SnakeContext *ctx, SnakeDirection dir) | ||
124 | { | ||
125 | SnakeCell ct = snake_cell_at(ctx, ctx->head_xpos, ctx->head_ypos); | ||
126 | if ((dir == SNAKE_DIR_RIGHT && ct != SNAKE_CELL_SLEFT) || | ||
127 | (dir == SNAKE_DIR_UP && ct != SNAKE_CELL_SDOWN) || | ||
128 | (dir == SNAKE_DIR_LEFT && ct != SNAKE_CELL_SRIGHT) || | ||
129 | (dir == SNAKE_DIR_DOWN && ct != SNAKE_CELL_SUP)) { | ||
130 | ctx->next_dir = dir; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void wrap_around_(char *val, char max) | ||
135 | { | ||
136 | if (*val < 0) { | ||
137 | *val = max - 1; | ||
138 | } else if (*val > max - 1) { | ||
139 | *val = 0; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | void snake_step(SnakeContext *ctx) | ||
144 | { | ||
145 | const SnakeCell dir_as_cell = (SnakeCell)(ctx->next_dir + 1); | ||
146 | SnakeCell ct; | ||
147 | char prev_xpos; | ||
148 | char prev_ypos; | ||
149 | /* Move tail forward */ | ||
150 | if (--ctx->inhibit_tail_step == 0) { | ||
151 | ++ctx->inhibit_tail_step; | ||
152 | ct = snake_cell_at(ctx, ctx->tail_xpos, ctx->tail_ypos); | ||
153 | put_cell_at_(ctx, ctx->tail_xpos, ctx->tail_ypos, SNAKE_CELL_NOTHING); | ||
154 | switch (ct) { | ||
155 | case SNAKE_CELL_SRIGHT: | ||
156 | ctx->tail_xpos++; | ||
157 | break; | ||
158 | case SNAKE_CELL_SUP: | ||
159 | ctx->tail_ypos--; | ||
160 | break; | ||
161 | case SNAKE_CELL_SLEFT: | ||
162 | ctx->tail_xpos--; | ||
163 | break; | ||
164 | case SNAKE_CELL_SDOWN: | ||
165 | ctx->tail_ypos++; | ||
166 | break; | ||
167 | default: | ||
168 | break; | ||
169 | } | ||
170 | wrap_around_(&ctx->tail_xpos, SNAKE_GAME_WIDTH); | ||
171 | wrap_around_(&ctx->tail_ypos, SNAKE_GAME_HEIGHT); | ||
172 | } | ||
173 | /* Move head forward */ | ||
174 | prev_xpos = ctx->head_xpos; | ||
175 | prev_ypos = ctx->head_ypos; | ||
176 | switch (ctx->next_dir) { | ||
177 | case SNAKE_DIR_RIGHT: | ||
178 | ++ctx->head_xpos; | ||
179 | break; | ||
180 | case SNAKE_DIR_UP: | ||
181 | --ctx->head_ypos; | ||
182 | break; | ||
183 | case SNAKE_DIR_LEFT: | ||
184 | --ctx->head_xpos; | ||
185 | break; | ||
186 | case SNAKE_DIR_DOWN: | ||
187 | ++ctx->head_ypos; | ||
188 | break; | ||
189 | } | ||
190 | wrap_around_(&ctx->head_xpos, SNAKE_GAME_WIDTH); | ||
191 | wrap_around_(&ctx->head_ypos, SNAKE_GAME_HEIGHT); | ||
192 | /* Collisions */ | ||
193 | ct = snake_cell_at(ctx, ctx->head_xpos, ctx->head_ypos); | ||
194 | if (ct != SNAKE_CELL_NOTHING && ct != SNAKE_CELL_FOOD) { | ||
195 | snake_initialize(ctx); | ||
196 | return; | ||
197 | } | ||
198 | put_cell_at_(ctx, prev_xpos, prev_ypos, dir_as_cell); | ||
199 | put_cell_at_(ctx, ctx->head_xpos, ctx->head_ypos, dir_as_cell); | ||
200 | if (ct == SNAKE_CELL_FOOD) { | ||
201 | if (are_cells_full_(ctx)) { | ||
202 | snake_initialize(ctx); | ||
203 | return; | ||
204 | } | ||
205 | new_food_pos_(ctx); | ||
206 | ++ctx->inhibit_tail_step; | ||
207 | ++ctx->occupied_cells; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static SDL_AppResult handle_key_event_(SnakeContext *ctx, SDL_Scancode key_code) | ||
212 | { | ||
213 | switch (key_code) { | ||
214 | /* Quit. */ | ||
215 | case SDL_SCANCODE_ESCAPE: | ||
216 | case SDL_SCANCODE_Q: | ||
217 | return SDL_APP_SUCCESS; | ||
218 | /* Restart the game as if the program was launched. */ | ||
219 | case SDL_SCANCODE_R: | ||
220 | snake_initialize(ctx); | ||
221 | break; | ||
222 | /* Decide new direction of the snake. */ | ||
223 | case SDL_SCANCODE_RIGHT: | ||
224 | snake_redir(ctx, SNAKE_DIR_RIGHT); | ||
225 | break; | ||
226 | case SDL_SCANCODE_UP: | ||
227 | snake_redir(ctx, SNAKE_DIR_UP); | ||
228 | break; | ||
229 | case SDL_SCANCODE_LEFT: | ||
230 | snake_redir(ctx, SNAKE_DIR_LEFT); | ||
231 | break; | ||
232 | case SDL_SCANCODE_DOWN: | ||
233 | snake_redir(ctx, SNAKE_DIR_DOWN); | ||
234 | break; | ||
235 | default: | ||
236 | break; | ||
237 | } | ||
238 | return SDL_APP_CONTINUE; | ||
239 | } | ||
240 | |||
241 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
242 | { | ||
243 | AppState *as = (AppState *)appstate; | ||
244 | SnakeContext *ctx = &as->snake_ctx; | ||
245 | const Uint64 now = SDL_GetTicks(); | ||
246 | SDL_FRect r; | ||
247 | unsigned i; | ||
248 | unsigned j; | ||
249 | int ct; | ||
250 | |||
251 | // run game logic if we're at or past the time to run it. | ||
252 | // if we're _really_ behind the time to run it, run it | ||
253 | // several times. | ||
254 | while ((now - as->last_step) >= STEP_RATE_IN_MILLISECONDS) { | ||
255 | snake_step(ctx); | ||
256 | as->last_step += STEP_RATE_IN_MILLISECONDS; | ||
257 | } | ||
258 | |||
259 | r.w = r.h = SNAKE_BLOCK_SIZE_IN_PIXELS; | ||
260 | SDL_SetRenderDrawColor(as->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); | ||
261 | SDL_RenderClear(as->renderer); | ||
262 | for (i = 0; i < SNAKE_GAME_WIDTH; i++) { | ||
263 | for (j = 0; j < SNAKE_GAME_HEIGHT; j++) { | ||
264 | ct = snake_cell_at(ctx, i, j); | ||
265 | if (ct == SNAKE_CELL_NOTHING) | ||
266 | continue; | ||
267 | set_rect_xy_(&r, i, j); | ||
268 | if (ct == SNAKE_CELL_FOOD) | ||
269 | SDL_SetRenderDrawColor(as->renderer, 80, 80, 255, SDL_ALPHA_OPAQUE); | ||
270 | else /* body */ | ||
271 | SDL_SetRenderDrawColor(as->renderer, 0, 128, 0, SDL_ALPHA_OPAQUE); | ||
272 | SDL_RenderFillRect(as->renderer, &r); | ||
273 | } | ||
274 | } | ||
275 | SDL_SetRenderDrawColor(as->renderer, 255, 255, 0, SDL_ALPHA_OPAQUE); /*head*/ | ||
276 | set_rect_xy_(&r, ctx->head_xpos, ctx->head_ypos); | ||
277 | SDL_RenderFillRect(as->renderer, &r); | ||
278 | SDL_RenderPresent(as->renderer); | ||
279 | return SDL_APP_CONTINUE; | ||
280 | } | ||
281 | |||
282 | static const struct | ||
283 | { | ||
284 | const char *key; | ||
285 | const char *value; | ||
286 | } extended_metadata[] = | ||
287 | { | ||
288 | { SDL_PROP_APP_METADATA_URL_STRING, "https://examples.libsdl.org/SDL3/demo/01-snake/" }, | ||
289 | { SDL_PROP_APP_METADATA_CREATOR_STRING, "SDL team" }, | ||
290 | { SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Placed in the public domain" }, | ||
291 | { SDL_PROP_APP_METADATA_TYPE_STRING, "game" } | ||
292 | }; | ||
293 | |||
294 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
295 | { | ||
296 | size_t i; | ||
297 | |||
298 | if (!SDL_SetAppMetadata("Example Snake game", "1.0", "com.example.Snake")) { | ||
299 | return SDL_APP_FAILURE; | ||
300 | } | ||
301 | |||
302 | for (i = 0; i < SDL_arraysize(extended_metadata); i++) { | ||
303 | if (!SDL_SetAppMetadataProperty(extended_metadata[i].key, extended_metadata[i].value)) { | ||
304 | return SDL_APP_FAILURE; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
309 | return SDL_APP_FAILURE; | ||
310 | } | ||
311 | |||
312 | AppState *as = (AppState *)SDL_calloc(1, sizeof(AppState)); | ||
313 | if (!as) { | ||
314 | return SDL_APP_FAILURE; | ||
315 | } | ||
316 | |||
317 | *appstate = as; | ||
318 | |||
319 | if (!SDL_CreateWindowAndRenderer("examples/demo/snake", SDL_WINDOW_WIDTH, SDL_WINDOW_HEIGHT, 0, &as->window, &as->renderer)) { | ||
320 | return SDL_APP_FAILURE; | ||
321 | } | ||
322 | |||
323 | snake_initialize(&as->snake_ctx); | ||
324 | |||
325 | as->last_step = SDL_GetTicks(); | ||
326 | |||
327 | return SDL_APP_CONTINUE; | ||
328 | } | ||
329 | |||
330 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
331 | { | ||
332 | SnakeContext *ctx = &((AppState *)appstate)->snake_ctx; | ||
333 | switch (event->type) { | ||
334 | case SDL_EVENT_QUIT: | ||
335 | return SDL_APP_SUCCESS; | ||
336 | case SDL_EVENT_KEY_DOWN: | ||
337 | return handle_key_event_(ctx, event->key.scancode); | ||
338 | } | ||
339 | return SDL_APP_CONTINUE; | ||
340 | } | ||
341 | |||
342 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
343 | { | ||
344 | if (appstate != NULL) { | ||
345 | AppState *as = (AppState *)appstate; | ||
346 | SDL_DestroyRenderer(as->renderer); | ||
347 | SDL_DestroyWindow(as->window); | ||
348 | SDL_free(as); | ||
349 | } | ||
350 | } | ||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/01-snake/thumbnail.png b/src/contrib/SDL-3.2.20/examples/demo/01-snake/thumbnail.png new file mode 100644 index 0000000..f0e27c5 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/01-snake/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/README.txt b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/README.txt new file mode 100644 index 0000000..83de3e3 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/README.txt | |||
@@ -0,0 +1 @@ | |||
Minimal splitscreen FPS with multiple mouse and keyboards, drawn with the 2D Render API. \ No newline at end of file | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/onmouseover.webp new file mode 100644 index 0000000..2e7f44f --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/thumbnail.png b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/thumbnail.png new file mode 100644 index 0000000..c8d1efa --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/woodeneye-008.c b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/woodeneye-008.c new file mode 100644 index 0000000..b97b06a --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/02-woodeneye-008/woodeneye-008.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /* | ||
2 | * This code is public domain. Feel free to use it for any purpose! | ||
3 | */ | ||
4 | |||
5 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
6 | #include <SDL3/SDL.h> | ||
7 | #include <SDL3/SDL_main.h> | ||
8 | |||
9 | #define MAP_BOX_SCALE 16 | ||
10 | #define MAP_BOX_EDGES_LEN (12 + MAP_BOX_SCALE * 2) | ||
11 | #define MAX_PLAYER_COUNT 4 | ||
12 | #define CIRCLE_DRAW_SIDES 32 | ||
13 | #define CIRCLE_DRAW_SIDES_LEN (CIRCLE_DRAW_SIDES + 1) | ||
14 | |||
15 | typedef struct { | ||
16 | SDL_MouseID mouse; | ||
17 | SDL_KeyboardID keyboard; | ||
18 | double pos[3]; | ||
19 | double vel[3]; | ||
20 | unsigned int yaw; | ||
21 | int pitch; | ||
22 | float radius, height; | ||
23 | unsigned char color[3]; | ||
24 | unsigned char wasd; | ||
25 | } Player; | ||
26 | |||
27 | typedef struct { | ||
28 | SDL_Window *window; | ||
29 | SDL_Renderer *renderer; | ||
30 | int player_count; | ||
31 | Player players[MAX_PLAYER_COUNT]; | ||
32 | float edges[MAP_BOX_EDGES_LEN][6]; | ||
33 | } AppState; | ||
34 | |||
35 | static const struct { | ||
36 | const char *key; | ||
37 | const char *value; | ||
38 | } extended_metadata[] = { | ||
39 | { SDL_PROP_APP_METADATA_URL_STRING, "https://examples.libsdl.org/SDL3/demo/02-woodeneye-008/" }, | ||
40 | { SDL_PROP_APP_METADATA_CREATOR_STRING, "SDL team" }, | ||
41 | { SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Placed in the public domain" }, | ||
42 | { SDL_PROP_APP_METADATA_TYPE_STRING, "game" } | ||
43 | }; | ||
44 | |||
45 | static int whoseMouse(SDL_MouseID mouse, const Player players[], int players_len) | ||
46 | { | ||
47 | int i; | ||
48 | for (i = 0; i < players_len; i++) { | ||
49 | if (players[i].mouse == mouse) return i; | ||
50 | } | ||
51 | return -1; | ||
52 | } | ||
53 | |||
54 | static int whoseKeyboard(SDL_KeyboardID keyboard, const Player players[], int players_len) | ||
55 | { | ||
56 | int i; | ||
57 | for (i = 0; i < players_len; i++) { | ||
58 | if (players[i].keyboard == keyboard) return i; | ||
59 | } | ||
60 | return -1; | ||
61 | } | ||
62 | |||
63 | static void shoot(int shooter, Player players[], int players_len) | ||
64 | { | ||
65 | int i, j; | ||
66 | double x0 = players[shooter].pos[0]; | ||
67 | double y0 = players[shooter].pos[1]; | ||
68 | double z0 = players[shooter].pos[2]; | ||
69 | double bin_rad = SDL_PI_D / 2147483648.0; | ||
70 | double yaw_rad = bin_rad * players[shooter].yaw; | ||
71 | double pitch_rad = bin_rad * players[shooter].pitch; | ||
72 | double cos_yaw = SDL_cos( yaw_rad); | ||
73 | double sin_yaw = SDL_sin( yaw_rad); | ||
74 | double cos_pitch = SDL_cos(pitch_rad); | ||
75 | double sin_pitch = SDL_sin(pitch_rad); | ||
76 | double vx = -sin_yaw*cos_pitch; | ||
77 | double vy = sin_pitch; | ||
78 | double vz = -cos_yaw*cos_pitch; | ||
79 | for (i = 0; i < players_len; i++) { | ||
80 | if (i == shooter) continue; | ||
81 | Player *target = &(players[i]); | ||
82 | int hit = 0; | ||
83 | for (j = 0; j < 2; j++) { | ||
84 | double r = target->radius; | ||
85 | double h = target->height; | ||
86 | double dx = target->pos[0] - x0; | ||
87 | double dy = target->pos[1] - y0 + (j == 0 ? 0 : r - h); | ||
88 | double dz = target->pos[2] - z0; | ||
89 | double vd = vx*dx + vy*dy + vz*dz; | ||
90 | double dd = dx*dx + dy*dy + dz*dz; | ||
91 | double vv = vx*vx + vy*vy + vz*vz; | ||
92 | double rr = r * r; | ||
93 | if (vd < 0) continue; | ||
94 | if (vd * vd >= vv * (dd - rr)) hit += 1; | ||
95 | } | ||
96 | if (hit) { | ||
97 | target->pos[0] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256; | ||
98 | target->pos[1] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256; | ||
99 | target->pos[2] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256; | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static void update(Player *players, int players_len, Uint64 dt_ns) | ||
105 | { | ||
106 | int i; | ||
107 | for (i = 0; i < players_len; i++) { | ||
108 | Player *player = &players[i]; | ||
109 | double rate = 6.0; | ||
110 | double time = (double)dt_ns * 1e-9; | ||
111 | double drag = SDL_exp(-time * rate); | ||
112 | double diff = 1.0 - drag; | ||
113 | double mult = 60.0; | ||
114 | double grav = 25.0; | ||
115 | double yaw = (double)player->yaw; | ||
116 | double rad = yaw * SDL_PI_D / 2147483648.0; | ||
117 | double cos = SDL_cos(rad); | ||
118 | double sin = SDL_sin(rad); | ||
119 | unsigned char wasd = player->wasd; | ||
120 | double dirX = (wasd & 8 ? 1.0 : 0.0) - (wasd & 2 ? 1.0 : 0.0); | ||
121 | double dirZ = (wasd & 4 ? 1.0 : 0.0) - (wasd & 1 ? 1.0 : 0.0); | ||
122 | double norm = dirX * dirX + dirZ * dirZ; | ||
123 | double accX = mult * (norm == 0 ? 0 : ( cos*dirX + sin*dirZ) / SDL_sqrt(norm)); | ||
124 | double accZ = mult * (norm == 0 ? 0 : (-sin*dirX + cos*dirZ) / SDL_sqrt(norm)); | ||
125 | double velX = player->vel[0]; | ||
126 | double velY = player->vel[1]; | ||
127 | double velZ = player->vel[2]; | ||
128 | player->vel[0] -= velX * diff; | ||
129 | player->vel[1] -= grav * time; | ||
130 | player->vel[2] -= velZ * diff; | ||
131 | player->vel[0] += diff * accX / rate; | ||
132 | player->vel[2] += diff * accZ / rate; | ||
133 | player->pos[0] += (time - diff/rate) * accX / rate + diff * velX / rate; | ||
134 | player->pos[1] += -0.5 * grav * time * time + velY * time; | ||
135 | player->pos[2] += (time - diff/rate) * accZ / rate + diff * velZ / rate; | ||
136 | double scale = (double)MAP_BOX_SCALE; | ||
137 | double bound = scale - player->radius; | ||
138 | double posX = SDL_max(SDL_min(bound, player->pos[0]), -bound); | ||
139 | double posY = SDL_max(SDL_min(bound, player->pos[1]), player->height - scale); | ||
140 | double posZ = SDL_max(SDL_min(bound, player->pos[2]), -bound); | ||
141 | if (player->pos[0] != posX) player->vel[0] = 0; | ||
142 | if (player->pos[1] != posY) player->vel[1] = (wasd & 16) ? 8.4375 : 0; | ||
143 | if (player->pos[2] != posZ) player->vel[2] = 0; | ||
144 | player->pos[0] = posX; | ||
145 | player->pos[1] = posY; | ||
146 | player->pos[2] = posZ; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static void drawCircle(SDL_Renderer *renderer, float r, float x, float y) | ||
151 | { | ||
152 | float ang; | ||
153 | SDL_FPoint points[CIRCLE_DRAW_SIDES_LEN]; | ||
154 | int i; | ||
155 | for (i = 0; i < CIRCLE_DRAW_SIDES_LEN; i++) { | ||
156 | ang = 2.0f * SDL_PI_F * (float)i / (float)CIRCLE_DRAW_SIDES; | ||
157 | points[i].x = x + r * SDL_cosf(ang); | ||
158 | points[i].y = y + r * SDL_sinf(ang); | ||
159 | } | ||
160 | SDL_RenderLines(renderer, (const SDL_FPoint*)&points, CIRCLE_DRAW_SIDES_LEN); | ||
161 | } | ||
162 | |||
163 | static void drawClippedSegment( | ||
164 | SDL_Renderer *renderer, | ||
165 | float ax, float ay, float az, | ||
166 | float bx, float by, float bz, | ||
167 | float x, float y, float z, float w) | ||
168 | { | ||
169 | if (az >= -w && bz >= -w) return; | ||
170 | float dx = ax - bx; | ||
171 | float dy = ay - by; | ||
172 | if (az > -w) { | ||
173 | float t = (-w - bz) / (az - bz); | ||
174 | ax = bx + dx * t; | ||
175 | ay = by + dy * t; | ||
176 | az = -w; | ||
177 | } else if (bz > -w) { | ||
178 | float t = (-w - az) / (bz - az); | ||
179 | bx = ax - dx * t; | ||
180 | by = ay - dy * t; | ||
181 | bz = -w; | ||
182 | } | ||
183 | ax = -z * ax / az; | ||
184 | ay = -z * ay / az; | ||
185 | bx = -z * bx / bz; | ||
186 | by = -z * by / bz; | ||
187 | SDL_RenderLine(renderer, x + ax, y - ay, x + bx, y - by); | ||
188 | } | ||
189 | |||
190 | static char debug_string[32]; | ||
191 | static void draw(SDL_Renderer *renderer, const float (*edges)[6], const Player players[], int players_len) | ||
192 | { | ||
193 | int w, h, i, j, k; | ||
194 | if (!SDL_GetRenderOutputSize(renderer, &w, &h)) { | ||
195 | return; | ||
196 | } | ||
197 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); | ||
198 | SDL_RenderClear(renderer); | ||
199 | if (players_len > 0) { | ||
200 | float wf = (float)w; | ||
201 | float hf = (float)h; | ||
202 | int part_hor = players_len > 2 ? 2 : 1; | ||
203 | int part_ver = players_len > 1 ? 2 : 1; | ||
204 | float size_hor = wf / ((float)part_hor); | ||
205 | float size_ver = hf / ((float)part_ver); | ||
206 | for (i = 0; i < players_len; i++) { | ||
207 | const Player *player = &players[i]; | ||
208 | float mod_x = (float)(i % part_hor); | ||
209 | float mod_y = (float)(i / part_hor); | ||
210 | float hor_origin = (mod_x + 0.5f) * size_hor; | ||
211 | float ver_origin = (mod_y + 0.5f) * size_ver; | ||
212 | float cam_origin = (float)(0.5 * SDL_sqrt(size_hor * size_hor + size_ver * size_ver)); | ||
213 | float hor_offset = mod_x * size_hor; | ||
214 | float ver_offset = mod_y * size_ver; | ||
215 | SDL_Rect rect; | ||
216 | rect.x = (int)hor_offset; | ||
217 | rect.y = (int)ver_offset; | ||
218 | rect.w = (int)size_hor; | ||
219 | rect.h = (int)size_ver; | ||
220 | SDL_SetRenderClipRect(renderer, &rect); | ||
221 | double x0 = player->pos[0]; | ||
222 | double y0 = player->pos[1]; | ||
223 | double z0 = player->pos[2]; | ||
224 | double bin_rad = SDL_PI_D / 2147483648.0; | ||
225 | double yaw_rad = bin_rad * player->yaw; | ||
226 | double pitch_rad = bin_rad * player->pitch; | ||
227 | double cos_yaw = SDL_cos( yaw_rad); | ||
228 | double sin_yaw = SDL_sin( yaw_rad); | ||
229 | double cos_pitch = SDL_cos(pitch_rad); | ||
230 | double sin_pitch = SDL_sin(pitch_rad); | ||
231 | double mat[9] = { | ||
232 | cos_yaw , 0, -sin_yaw , | ||
233 | sin_yaw*sin_pitch, cos_pitch, cos_yaw*sin_pitch, | ||
234 | sin_yaw*cos_pitch, -sin_pitch, cos_yaw*cos_pitch | ||
235 | }; | ||
236 | SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255); | ||
237 | for (k = 0; k < MAP_BOX_EDGES_LEN; k++) { | ||
238 | const float *line = edges[k]; | ||
239 | float ax = (float)(mat[0] * (line[0] - x0) + mat[1] * (line[1] - y0) + mat[2] * (line[2] - z0)); | ||
240 | float ay = (float)(mat[3] * (line[0] - x0) + mat[4] * (line[1] - y0) + mat[5] * (line[2] - z0)); | ||
241 | float az = (float)(mat[6] * (line[0] - x0) + mat[7] * (line[1] - y0) + mat[8] * (line[2] - z0)); | ||
242 | float bx = (float)(mat[0] * (line[3] - x0) + mat[1] * (line[4] - y0) + mat[2] * (line[5] - z0)); | ||
243 | float by = (float)(mat[3] * (line[3] - x0) + mat[4] * (line[4] - y0) + mat[5] * (line[5] - z0)); | ||
244 | float bz = (float)(mat[6] * (line[3] - x0) + mat[7] * (line[4] - y0) + mat[8] * (line[5] - z0)); | ||
245 | drawClippedSegment(renderer, ax, ay, az, bx, by, bz, hor_origin, ver_origin, cam_origin, 1); | ||
246 | } | ||
247 | for (j = 0; j < players_len; j++) { | ||
248 | if (i == j) continue; | ||
249 | const Player *target = &players[j]; | ||
250 | SDL_SetRenderDrawColor(renderer, target->color[0], target->color[1], target->color[2], 255); | ||
251 | for (k = 0; k < 2; k++) { | ||
252 | double rx = target->pos[0] - player->pos[0]; | ||
253 | double ry = target->pos[1] - player->pos[1] + (target->radius - target->height) * (float)k; | ||
254 | double rz = target->pos[2] - player->pos[2]; | ||
255 | double dx = mat[0] * rx + mat[1] * ry + mat[2] * rz; | ||
256 | double dy = mat[3] * rx + mat[4] * ry + mat[5] * rz; | ||
257 | double dz = mat[6] * rx + mat[7] * ry + mat[8] * rz; | ||
258 | double r_eff = target->radius * cam_origin / dz; | ||
259 | if (!(dz < 0)) continue; | ||
260 | drawCircle(renderer, (float)(r_eff), (float)(hor_origin - cam_origin*dx/dz), (float)(ver_origin + cam_origin*dy/dz)); | ||
261 | } | ||
262 | } | ||
263 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
264 | SDL_RenderLine(renderer, hor_origin, ver_origin-10, hor_origin, ver_origin+10); | ||
265 | SDL_RenderLine(renderer, hor_origin-10, ver_origin, hor_origin+10, ver_origin); | ||
266 | } | ||
267 | } | ||
268 | SDL_SetRenderClipRect(renderer, 0); | ||
269 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
270 | SDL_RenderDebugText(renderer, 0, 0, debug_string); | ||
271 | SDL_RenderPresent(renderer); | ||
272 | } | ||
273 | |||
274 | static void initPlayers(Player *players, int len) | ||
275 | { | ||
276 | int i; | ||
277 | for (i = 0; i < len; i++) { | ||
278 | players[i].pos[0] = 8.0 * (i & 1 ? -1.0 : 1.0); | ||
279 | players[i].pos[1] = 0; | ||
280 | players[i].pos[2] = 8.0 * (i & 1 ? -1.0 : 1.0) * (i & 2 ? -1.0 : 1.0); | ||
281 | players[i].vel[0] = 0; | ||
282 | players[i].vel[1] = 0; | ||
283 | players[i].vel[2] = 0; | ||
284 | players[i].yaw = 0x20000000 + (i & 1 ? 0x80000000 : 0) + (i & 2 ? 0x40000000 : 0); | ||
285 | players[i].pitch = -0x08000000; | ||
286 | players[i].radius = 0.5f; | ||
287 | players[i].height = 1.5f; | ||
288 | players[i].wasd = 0; | ||
289 | players[i].mouse = 0; | ||
290 | players[i].keyboard = 0; | ||
291 | players[i].color[0] = (1 << (i / 2)) & 2 ? 0 : 0xff; | ||
292 | players[i].color[1] = (1 << (i / 2)) & 1 ? 0 : 0xff; | ||
293 | players[i].color[2] = (1 << (i / 2)) & 4 ? 0 : 0xff; | ||
294 | players[i].color[0] = (i & 1) ? players[i].color[0] : ~players[i].color[0]; | ||
295 | players[i].color[1] = (i & 1) ? players[i].color[1] : ~players[i].color[1]; | ||
296 | players[i].color[2] = (i & 1) ? players[i].color[2] : ~players[i].color[2]; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static void initEdges(int scale, float (*edges)[6], int edges_len) | ||
301 | { | ||
302 | int i, j; | ||
303 | const float r = (float)scale; | ||
304 | const int map[24] = { | ||
305 | 0,1 , 1,3 , 3,2 , 2,0 , | ||
306 | 7,6 , 6,4 , 4,5 , 5,7 , | ||
307 | 6,2 , 3,7 , 0,4 , 5,1 | ||
308 | }; | ||
309 | for(i = 0; i < 12; i++) { | ||
310 | for (j = 0; j < 3; j++) { | ||
311 | edges[i][j+0] = (map[i*2+0] & (1 << j) ? r : -r); | ||
312 | edges[i][j+3] = (map[i*2+1] & (1 << j) ? r : -r); | ||
313 | } | ||
314 | } | ||
315 | for(i = 0; i < scale; i++) { | ||
316 | float d = (float)(i * 2); | ||
317 | for (j = 0; j < 2; j++) { | ||
318 | edges[i+12][3*j+0] = j ? r : -r; | ||
319 | edges[i+12][3*j+1] = -r; | ||
320 | edges[i+12][3*j+2] = d-r; | ||
321 | edges[i+12+scale][3*j+0] = d-r; | ||
322 | edges[i+12+scale][3*j+1] = -r; | ||
323 | edges[i+12+scale][3*j+2] = j ? r : -r; | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | |||
328 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
329 | { | ||
330 | if (!SDL_SetAppMetadata("Example splitscreen shooter game", "1.0", "com.example.woodeneye-008")) { | ||
331 | return SDL_APP_FAILURE; | ||
332 | } | ||
333 | int i; | ||
334 | for (i = 0; i < SDL_arraysize(extended_metadata); i++) { | ||
335 | if (!SDL_SetAppMetadataProperty(extended_metadata[i].key, extended_metadata[i].value)) { | ||
336 | return SDL_APP_FAILURE; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | AppState *as = SDL_calloc(1, sizeof(AppState)); | ||
341 | if (!as) { | ||
342 | return SDL_APP_FAILURE; | ||
343 | } else { | ||
344 | *appstate = as; | ||
345 | } | ||
346 | |||
347 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
348 | return SDL_APP_FAILURE; | ||
349 | } | ||
350 | if (!SDL_CreateWindowAndRenderer("examples/demo/woodeneye-008", 640, 480, 0, &as->window, &as->renderer)) { | ||
351 | return SDL_APP_FAILURE; | ||
352 | } | ||
353 | |||
354 | as->player_count = 1; | ||
355 | initPlayers(as->players, MAX_PLAYER_COUNT); | ||
356 | initEdges(MAP_BOX_SCALE, as->edges, MAP_BOX_EDGES_LEN); | ||
357 | debug_string[0] = 0; | ||
358 | |||
359 | SDL_SetRenderVSync(as->renderer, false); | ||
360 | SDL_SetWindowRelativeMouseMode(as->window, true); | ||
361 | SDL_SetHintWithPriority(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1", SDL_HINT_OVERRIDE); | ||
362 | return SDL_APP_CONTINUE; | ||
363 | } | ||
364 | |||
365 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
366 | { | ||
367 | AppState *as = appstate; | ||
368 | Player *players = as->players; | ||
369 | int player_count = as->player_count; | ||
370 | int i; | ||
371 | switch (event->type) { | ||
372 | case SDL_EVENT_QUIT: | ||
373 | return SDL_APP_SUCCESS; | ||
374 | break; | ||
375 | case SDL_EVENT_MOUSE_REMOVED: | ||
376 | for (i = 0; i < player_count; i++) { | ||
377 | if (players[i].mouse == event->mdevice.which) { | ||
378 | players[i].mouse = 0; | ||
379 | } | ||
380 | } | ||
381 | break; | ||
382 | case SDL_EVENT_KEYBOARD_REMOVED: | ||
383 | for (i = 0; i < player_count; i++) { | ||
384 | if (players[i].keyboard == event->kdevice.which) { | ||
385 | players[i].keyboard = 0; | ||
386 | } | ||
387 | } | ||
388 | break; | ||
389 | case SDL_EVENT_MOUSE_MOTION: { | ||
390 | SDL_MouseID id = event->motion.which; | ||
391 | int index = whoseMouse(id, players, player_count); | ||
392 | if (index >= 0) { | ||
393 | players[index].yaw -= ((int)event->motion.xrel) * 0x00080000; | ||
394 | players[index].pitch = SDL_max(-0x40000000, SDL_min(0x40000000, players[index].pitch - ((int)event->motion.yrel) * 0x00080000)); | ||
395 | } else if (id) { | ||
396 | for (i = 0; i < MAX_PLAYER_COUNT; i++) { | ||
397 | if (players[i].mouse == 0) { | ||
398 | players[i].mouse = id; | ||
399 | as->player_count = SDL_max(as->player_count, i + 1); | ||
400 | break; | ||
401 | } | ||
402 | } | ||
403 | } | ||
404 | break; | ||
405 | } | ||
406 | case SDL_EVENT_MOUSE_BUTTON_DOWN: { | ||
407 | SDL_MouseID id = event->button.which; | ||
408 | int index = whoseMouse(id, players, player_count); | ||
409 | if (index >= 0) { | ||
410 | shoot(index, players, player_count); | ||
411 | } | ||
412 | break; | ||
413 | } | ||
414 | case SDL_EVENT_KEY_DOWN: { | ||
415 | SDL_Keycode sym = event->key.key; | ||
416 | SDL_KeyboardID id = event->key.which; | ||
417 | int index = whoseKeyboard(id, players, player_count); | ||
418 | if (index >= 0) { | ||
419 | if (sym == SDLK_W) players[index].wasd |= 1; | ||
420 | if (sym == SDLK_A) players[index].wasd |= 2; | ||
421 | if (sym == SDLK_S) players[index].wasd |= 4; | ||
422 | if (sym == SDLK_D) players[index].wasd |= 8; | ||
423 | if (sym == SDLK_SPACE) players[index].wasd |= 16; | ||
424 | } else if (id) { | ||
425 | for (i = 0; i < MAX_PLAYER_COUNT; i++) { | ||
426 | if (players[i].keyboard == 0) { | ||
427 | players[i].keyboard = id; | ||
428 | as->player_count = SDL_max(as->player_count, i + 1); | ||
429 | break; | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | break; | ||
434 | } | ||
435 | case SDL_EVENT_KEY_UP: { | ||
436 | SDL_Keycode sym = event->key.key; | ||
437 | SDL_KeyboardID id = event->key.which; | ||
438 | if (sym == SDLK_ESCAPE) return SDL_APP_SUCCESS; | ||
439 | int index = whoseKeyboard(id, players, player_count); | ||
440 | if (index >= 0) { | ||
441 | if (sym == SDLK_W) players[index].wasd &= 30; | ||
442 | if (sym == SDLK_A) players[index].wasd &= 29; | ||
443 | if (sym == SDLK_S) players[index].wasd &= 27; | ||
444 | if (sym == SDLK_D) players[index].wasd &= 23; | ||
445 | if (sym == SDLK_SPACE) players[index].wasd &= 15; | ||
446 | } | ||
447 | break; | ||
448 | } | ||
449 | } | ||
450 | return SDL_APP_CONTINUE; | ||
451 | } | ||
452 | |||
453 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
454 | { | ||
455 | AppState *as = appstate; | ||
456 | static Uint64 accu = 0; | ||
457 | static Uint64 last = 0; | ||
458 | static Uint64 past = 0; | ||
459 | Uint64 now = SDL_GetTicksNS(); | ||
460 | Uint64 dt_ns = now - past; | ||
461 | update(as->players, as->player_count, dt_ns); | ||
462 | draw(as->renderer, (const float (*)[6])as->edges, as->players, as->player_count); | ||
463 | if (now - last > 999999999) { | ||
464 | last = now; | ||
465 | SDL_snprintf(debug_string, sizeof(debug_string), "%" SDL_PRIu64 " fps", accu); | ||
466 | accu = 0; | ||
467 | } | ||
468 | past = now; | ||
469 | accu += 1; | ||
470 | Uint64 elapsed = SDL_GetTicksNS() - now; | ||
471 | if (elapsed < 999999) { | ||
472 | SDL_DelayNS(999999 - elapsed); | ||
473 | } | ||
474 | return SDL_APP_CONTINUE; | ||
475 | } | ||
476 | |||
477 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
478 | { | ||
479 | SDL_free(appstate); // just free the memory, SDL will clean up the window/renderer for us. | ||
480 | } \ No newline at end of file | ||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/README.txt b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/README.txt new file mode 100644 index 0000000..3a80b69 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/README.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | |||
2 | How many monkeys does it take to write the complete works of Shakespeare? | ||
3 | |||
4 | Now you can find out! | ||
5 | |||
6 | Cheer on your favorite monkey as they bash keyboards on their way through classic literature. | ||
7 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/infinite-monkeys.c b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/infinite-monkeys.c new file mode 100644 index 0000000..a8bfad1 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/infinite-monkeys.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | * This code is public domain. Feel free to use it for any purpose! | ||
3 | */ | ||
4 | |||
5 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
6 | #include <SDL3/SDL.h> | ||
7 | #include <SDL3/SDL_main.h> | ||
8 | |||
9 | /* We will use this renderer to draw into this window every frame. */ | ||
10 | static SDL_Window *window = NULL; | ||
11 | static SDL_Renderer *renderer = NULL; | ||
12 | static char *text; | ||
13 | static const char *end; | ||
14 | static const char *progress; | ||
15 | static SDL_Time start_time; | ||
16 | static SDL_Time end_time; | ||
17 | typedef struct { | ||
18 | Uint32 *text; | ||
19 | int length; | ||
20 | } Line; | ||
21 | int row = 0; | ||
22 | int rows = 0; | ||
23 | int cols = 0; | ||
24 | static Line **lines; | ||
25 | static Line monkey_chars; | ||
26 | static int monkeys = 100; | ||
27 | |||
28 | /* The highest and lowest scancodes a monkey can hit */ | ||
29 | #define MIN_MONKEY_SCANCODE SDL_SCANCODE_A | ||
30 | #define MAX_MONKEY_SCANCODE SDL_SCANCODE_SLASH | ||
31 | |||
32 | static const char *default_text = | ||
33 | "Jabberwocky, by Lewis Carroll\n" | ||
34 | "\n" | ||
35 | "'Twas brillig, and the slithy toves\n" | ||
36 | " Did gyre and gimble in the wabe:\n" | ||
37 | "All mimsy were the borogoves,\n" | ||
38 | " And the mome raths outgrabe.\n" | ||
39 | "\n" | ||
40 | "\"Beware the Jabberwock, my son!\n" | ||
41 | " The jaws that bite, the claws that catch!\n" | ||
42 | "Beware the Jubjub bird, and shun\n" | ||
43 | " The frumious Bandersnatch!\"\n" | ||
44 | "\n" | ||
45 | "He took his vorpal sword in hand;\n" | ||
46 | " Long time the manxome foe he sought-\n" | ||
47 | "So rested he by the Tumtum tree\n" | ||
48 | " And stood awhile in thought.\n" | ||
49 | "\n" | ||
50 | "And, as in uffish thought he stood,\n" | ||
51 | " The Jabberwock, with eyes of flame,\n" | ||
52 | "Came whiffling through the tulgey wood,\n" | ||
53 | " And burbled as it came!\n" | ||
54 | "\n" | ||
55 | "One, two! One, two! And through and through\n" | ||
56 | " The vorpal blade went snicker-snack!\n" | ||
57 | "He left it dead, and with its head\n" | ||
58 | " He went galumphing back.\n" | ||
59 | "\n" | ||
60 | "\"And hast thou slain the Jabberwock?\n" | ||
61 | " Come to my arms, my beamish boy!\n" | ||
62 | "O frabjous day! Callooh! Callay!\"\n" | ||
63 | " He chortled in his joy.\n" | ||
64 | "\n" | ||
65 | "'Twas brillig, and the slithy toves\n" | ||
66 | " Did gyre and gimble in the wabe:\n" | ||
67 | "All mimsy were the borogoves,\n" | ||
68 | " And the mome raths outgrabe.\n"; | ||
69 | |||
70 | |||
71 | static void FreeLines(void) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | if (rows > 0 && cols > 0) { | ||
76 | for (i = 0; i < rows; ++i) { | ||
77 | SDL_free(lines[i]->text); | ||
78 | SDL_free(lines[i]); | ||
79 | } | ||
80 | SDL_free(lines); | ||
81 | lines = NULL; | ||
82 | } | ||
83 | SDL_free(monkey_chars.text); | ||
84 | monkey_chars.text = NULL; | ||
85 | } | ||
86 | |||
87 | static void OnWindowSizeChanged(void) | ||
88 | { | ||
89 | int w, h; | ||
90 | |||
91 | if (!SDL_GetCurrentRenderOutputSize(renderer, &w, &h)) { | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | FreeLines(); | ||
96 | |||
97 | row = 0; | ||
98 | rows = (h / SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) - 4; | ||
99 | cols = (w / SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE); | ||
100 | if (rows > 0 && cols > 0) { | ||
101 | int i; | ||
102 | |||
103 | lines = (Line **)SDL_malloc(rows * sizeof(Line *)); | ||
104 | if (lines) { | ||
105 | for (i = 0; i < rows; ++i) { | ||
106 | lines[i] = (Line *)SDL_malloc(sizeof(Line)); | ||
107 | if (!lines[i]) { | ||
108 | FreeLines(); | ||
109 | break; | ||
110 | } | ||
111 | lines[i]->text = (Uint32 *)SDL_malloc(cols * sizeof(Uint32)); | ||
112 | if (!lines[i]->text) { | ||
113 | FreeLines(); | ||
114 | break; | ||
115 | } | ||
116 | lines[i]->length = 0; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | monkey_chars.text = (Uint32 *)SDL_malloc(cols * sizeof(Uint32)); | ||
121 | if (monkey_chars.text) { | ||
122 | for (i = 0; i < cols; ++i) { | ||
123 | monkey_chars.text[i] = ' '; | ||
124 | } | ||
125 | monkey_chars.length = cols; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | /* This function runs once at startup. */ | ||
131 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
132 | { | ||
133 | int arg = 1; | ||
134 | |||
135 | SDL_SetAppMetadata("Infinite Monkeys", "1.0", "com.example.infinite-monkeys"); | ||
136 | |||
137 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
138 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
139 | return SDL_APP_FAILURE; | ||
140 | } | ||
141 | |||
142 | if (!SDL_CreateWindowAndRenderer("examples/demo/infinite-monkeys", 640, 480, 0, &window, &renderer)) { | ||
143 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
144 | return SDL_APP_FAILURE; | ||
145 | } | ||
146 | SDL_SetRenderVSync(renderer, 1); | ||
147 | |||
148 | if (argv[arg] && SDL_strcmp(argv[arg], "--monkeys") == 0) { | ||
149 | ++arg; | ||
150 | if (argv[arg]) { | ||
151 | monkeys = SDL_atoi(argv[arg]); | ||
152 | ++arg; | ||
153 | } else { | ||
154 | SDL_Log("Usage: %s [--monkeys N] [file.txt]", argv[0]); | ||
155 | return SDL_APP_FAILURE; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | if (argv[arg]) { | ||
160 | const char *file = argv[arg]; | ||
161 | size_t size; | ||
162 | text = (char *)SDL_LoadFile(file, &size); | ||
163 | if (!text) { | ||
164 | SDL_Log("Couldn't open %s: %s", file, SDL_GetError()); | ||
165 | return SDL_APP_FAILURE; | ||
166 | } | ||
167 | end = text + size; | ||
168 | } else { | ||
169 | text = SDL_strdup(default_text); | ||
170 | end = text + SDL_strlen(text); | ||
171 | } | ||
172 | progress = text; | ||
173 | |||
174 | SDL_GetCurrentTime(&start_time); | ||
175 | |||
176 | OnWindowSizeChanged(); | ||
177 | |||
178 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
179 | } | ||
180 | |||
181 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
182 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
183 | { | ||
184 | switch (event->type) { | ||
185 | case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: | ||
186 | OnWindowSizeChanged(); | ||
187 | break; | ||
188 | case SDL_EVENT_QUIT: | ||
189 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
190 | } | ||
191 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
192 | } | ||
193 | |||
194 | static void DisplayLine(float x, float y, Line *line) | ||
195 | { | ||
196 | /* Allocate maximum space potentially needed for this line */ | ||
197 | char *utf8 = (char *)SDL_malloc(line->length * 4 + 1); | ||
198 | if (utf8) { | ||
199 | char *spot = utf8; | ||
200 | int i; | ||
201 | |||
202 | for (i = 0; i < line->length; ++i) { | ||
203 | spot = SDL_UCS4ToUTF8(line->text[i], spot); | ||
204 | } | ||
205 | *spot = '\0'; | ||
206 | |||
207 | SDL_RenderDebugText(renderer, x, y, utf8); | ||
208 | SDL_free(utf8); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static bool CanMonkeyType(Uint32 ch) | ||
213 | { | ||
214 | SDL_Keymod modstate; | ||
215 | SDL_Scancode scancode = SDL_GetScancodeFromKey(ch, &modstate); | ||
216 | if (scancode < MIN_MONKEY_SCANCODE || scancode > MAX_MONKEY_SCANCODE) { | ||
217 | return false; | ||
218 | } | ||
219 | /* Monkeys can hit the shift key, but nothing else */ | ||
220 | if ((modstate & ~SDL_KMOD_SHIFT) != 0) { | ||
221 | return false; | ||
222 | } | ||
223 | return true; | ||
224 | } | ||
225 | |||
226 | static void AdvanceRow(void) | ||
227 | { | ||
228 | Line *line; | ||
229 | |||
230 | ++row; | ||
231 | line = lines[row % rows]; | ||
232 | line->length = 0; | ||
233 | } | ||
234 | |||
235 | static void AddMonkeyChar(int monkey, Uint32 ch) | ||
236 | { | ||
237 | if (monkey >= 0 && monkey_chars.text) { | ||
238 | monkey_chars.text[(monkey % cols)] = ch; | ||
239 | } | ||
240 | |||
241 | if (lines) { | ||
242 | if (ch == '\n') { | ||
243 | AdvanceRow(); | ||
244 | } else { | ||
245 | Line *line = lines[row % rows]; | ||
246 | line->text[line->length++] = ch; | ||
247 | if (line->length == cols) { | ||
248 | AdvanceRow(); | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | SDL_StepUTF8(&progress, NULL); | ||
254 | } | ||
255 | |||
256 | static Uint32 GetNextChar(void) | ||
257 | { | ||
258 | Uint32 ch = 0; | ||
259 | while (progress < end) { | ||
260 | const char *spot = progress; | ||
261 | ch = SDL_StepUTF8(&spot, NULL); | ||
262 | if (CanMonkeyType(ch)) { | ||
263 | break; | ||
264 | } else { | ||
265 | /* This is a freebie, monkeys can't type this */ | ||
266 | AddMonkeyChar(-1, ch); | ||
267 | } | ||
268 | } | ||
269 | return ch; | ||
270 | } | ||
271 | |||
272 | static Uint32 MonkeyPlay(void) | ||
273 | { | ||
274 | int count = (MAX_MONKEY_SCANCODE - MIN_MONKEY_SCANCODE + 1); | ||
275 | SDL_Scancode scancode = (SDL_Scancode)(MIN_MONKEY_SCANCODE + SDL_rand(count)); | ||
276 | SDL_Keymod modstate = (SDL_rand(2) ? SDL_KMOD_SHIFT : 0); | ||
277 | |||
278 | return SDL_GetKeyFromScancode(scancode, modstate, false); | ||
279 | } | ||
280 | |||
281 | /* This function runs once per frame, and is the heart of the program. */ | ||
282 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
283 | { | ||
284 | int i, monkey; | ||
285 | Uint32 next_char = 0, ch; | ||
286 | float x, y; | ||
287 | char *caption = NULL; | ||
288 | SDL_Time now, elapsed; | ||
289 | int hours, minutes, seconds; | ||
290 | SDL_FRect rect; | ||
291 | |||
292 | for (monkey = 0; monkey < monkeys; ++monkey) { | ||
293 | if (next_char == 0) { | ||
294 | next_char = GetNextChar(); | ||
295 | if (!next_char) { | ||
296 | /* All done! */ | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | ch = MonkeyPlay(); | ||
302 | if (ch == next_char) { | ||
303 | AddMonkeyChar(monkey, ch); | ||
304 | next_char = 0; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | /* Clear the screen */ | ||
309 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); | ||
310 | SDL_RenderClear(renderer); | ||
311 | |||
312 | /* Show the text already decoded */ | ||
313 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); | ||
314 | x = 0.0f; | ||
315 | y = 0.0f; | ||
316 | if (lines) { | ||
317 | int row_offset = row - rows + 1; | ||
318 | if (row_offset < 0) { | ||
319 | row_offset = 0; | ||
320 | } | ||
321 | for (i = 0; i < rows; ++i) { | ||
322 | Line *line = lines[(row_offset + i) % rows]; | ||
323 | DisplayLine(x, y, line); | ||
324 | y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE; | ||
325 | } | ||
326 | |||
327 | /* Show the caption */ | ||
328 | y = (float)((rows + 1) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE); | ||
329 | if (progress == end) { | ||
330 | if (!end_time) { | ||
331 | SDL_GetCurrentTime(&end_time); | ||
332 | } | ||
333 | now = end_time; | ||
334 | } else { | ||
335 | SDL_GetCurrentTime(&now); | ||
336 | } | ||
337 | elapsed = (now - start_time); | ||
338 | elapsed /= SDL_NS_PER_SECOND; | ||
339 | seconds = (int)(elapsed % 60); | ||
340 | elapsed /= 60; | ||
341 | minutes = (int)(elapsed % 60); | ||
342 | elapsed /= 60; | ||
343 | hours = (int)elapsed; | ||
344 | SDL_asprintf(&caption, "Monkeys: %d - %dH:%dM:%dS", monkeys, hours, minutes, seconds); | ||
345 | if (caption) { | ||
346 | SDL_RenderDebugText(renderer, x, y, caption); | ||
347 | SDL_free(caption); | ||
348 | } | ||
349 | y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE; | ||
350 | |||
351 | /* Show the characters currently typed */ | ||
352 | DisplayLine(x, y, &monkey_chars); | ||
353 | y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE; | ||
354 | } | ||
355 | |||
356 | /* Show the current progress */ | ||
357 | SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); | ||
358 | rect.x = x; | ||
359 | rect.y = y; | ||
360 | rect.w = ((float)(progress - text) / (end - text)) * (cols * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE); | ||
361 | rect.h = (float)SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE; | ||
362 | SDL_RenderFillRect(renderer, &rect); | ||
363 | |||
364 | SDL_RenderPresent(renderer); | ||
365 | |||
366 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
367 | } | ||
368 | |||
369 | /* This function runs once at shutdown. */ | ||
370 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
371 | { | ||
372 | /* SDL will clean up the window/renderer for us. */ | ||
373 | |||
374 | FreeLines(); | ||
375 | SDL_free(text); | ||
376 | } | ||
377 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/onmouseover.webp new file mode 100644 index 0000000..f522974 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/thumbnail.png b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/thumbnail.png new file mode 100644 index 0000000..418390b --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/03-infinite-monkeys/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/README.txt b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/README.txt new file mode 100644 index 0000000..dbee4ce --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/README.txt | |||
@@ -0,0 +1,4 @@ | |||
1 | An implementation of the BytePusher VM | ||
2 | |||
3 | For example programs and more information about BytePusher, see | ||
4 | https://esolangs.org/wiki/BytePusher | ||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/bytepusher.c b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/bytepusher.c new file mode 100644 index 0000000..acb2ea4 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/bytepusher.c | |||
@@ -0,0 +1,416 @@ | |||
1 | /* | ||
2 | * An implementation of the BytePusher VM. | ||
3 | * | ||
4 | * For example programs and more information about BytePusher, see | ||
5 | * https://esolangs.org/wiki/BytePusher | ||
6 | * | ||
7 | * This code is public domain. Feel free to use it for any purpose! | ||
8 | */ | ||
9 | |||
10 | #define SDL_MAIN_USE_CALLBACKS | ||
11 | #include <SDL3/SDL.h> | ||
12 | #include <SDL3/SDL_main.h> | ||
13 | #include <stdarg.h> | ||
14 | |||
15 | #define SCREEN_W 256 | ||
16 | #define SCREEN_H 256 | ||
17 | #define RAM_SIZE 0x1000000 | ||
18 | #define FRAMES_PER_SECOND 60 | ||
19 | #define SAMPLES_PER_FRAME 256 | ||
20 | #define NS_PER_SECOND (Uint64)SDL_NS_PER_SECOND | ||
21 | #define MAX_AUDIO_LATENCY_FRAMES 5 | ||
22 | |||
23 | #define IO_KEYBOARD 0 | ||
24 | #define IO_PC 2 | ||
25 | #define IO_SCREEN_PAGE 5 | ||
26 | #define IO_AUDIO_BANK 6 | ||
27 | |||
28 | typedef struct { | ||
29 | Uint8 ram[RAM_SIZE + 8]; | ||
30 | Uint8 screenbuf[SCREEN_W * SCREEN_H]; | ||
31 | Uint64 last_tick; | ||
32 | Uint64 tick_acc; | ||
33 | SDL_Window* window; | ||
34 | SDL_Renderer* renderer; | ||
35 | SDL_Surface* screen; | ||
36 | SDL_Texture* screentex; | ||
37 | SDL_Texture* rendertarget; /* we need this render target for text to look good */ | ||
38 | SDL_AudioStream* audiostream; | ||
39 | char status[SCREEN_W / 8]; | ||
40 | int status_ticks; | ||
41 | Uint16 keystate; | ||
42 | bool display_help; | ||
43 | bool positional_input; | ||
44 | } BytePusher; | ||
45 | |||
46 | static const struct { | ||
47 | const char *key; | ||
48 | const char *value; | ||
49 | } extended_metadata[] = { | ||
50 | { SDL_PROP_APP_METADATA_URL_STRING, "https://examples.libsdl.org/SDL3/demo/04-bytepusher/" }, | ||
51 | { SDL_PROP_APP_METADATA_CREATOR_STRING, "SDL team" }, | ||
52 | { SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Placed in the public domain" }, | ||
53 | { SDL_PROP_APP_METADATA_TYPE_STRING, "game" } | ||
54 | }; | ||
55 | |||
56 | static inline Uint16 read_u16(const BytePusher* vm, Uint32 addr) { | ||
57 | const Uint8* ptr = &vm->ram[addr]; | ||
58 | return ((Uint16)ptr[0] << 8) | ((Uint16)ptr[1]); | ||
59 | } | ||
60 | |||
61 | static inline Uint32 read_u24(const BytePusher* vm, Uint32 addr) { | ||
62 | const Uint8* ptr = &vm->ram[addr]; | ||
63 | return ((Uint32)ptr[0] << 16) | ((Uint32)ptr[1] << 8) | ((Uint32)ptr[2]); | ||
64 | } | ||
65 | |||
66 | static void set_status(BytePusher* vm, const char* fmt, ...) { | ||
67 | va_list args; | ||
68 | va_start(args, fmt); | ||
69 | SDL_vsnprintf(vm->status, sizeof(vm->status), fmt, args); | ||
70 | va_end(args); | ||
71 | vm->status[sizeof(vm->status) - 1] = 0; | ||
72 | vm->status_ticks = FRAMES_PER_SECOND * 3; | ||
73 | } | ||
74 | |||
75 | static bool load(BytePusher* vm, SDL_IOStream* stream, bool closeio) { | ||
76 | size_t bytes_read = 0; | ||
77 | bool ok = true; | ||
78 | |||
79 | SDL_memset(vm->ram, 0, RAM_SIZE); | ||
80 | |||
81 | if (!stream) { | ||
82 | return false; | ||
83 | } | ||
84 | |||
85 | while (bytes_read < RAM_SIZE) { | ||
86 | size_t read = SDL_ReadIO(stream, &vm->ram[bytes_read], RAM_SIZE - bytes_read); | ||
87 | bytes_read += read; | ||
88 | if (read == 0) { | ||
89 | ok = SDL_GetIOStatus(stream) == SDL_IO_STATUS_EOF; | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | if (closeio) { | ||
94 | SDL_CloseIO(stream); | ||
95 | } | ||
96 | |||
97 | SDL_ClearAudioStream(vm->audiostream); | ||
98 | |||
99 | vm->display_help = !ok; | ||
100 | return ok; | ||
101 | } | ||
102 | |||
103 | static const char* filename(const char* path) { | ||
104 | size_t i = SDL_strlen(path) + 1; | ||
105 | while (i > 0) { | ||
106 | i -= 1; | ||
107 | if (path[i] == '/' || path[i] == '\\') { | ||
108 | return path + i + 1; | ||
109 | } | ||
110 | } | ||
111 | return path; | ||
112 | } | ||
113 | |||
114 | static bool load_file(BytePusher* vm, const char* path) { | ||
115 | if (load(vm, SDL_IOFromFile(path, "rb"), true)) { | ||
116 | set_status(vm, "loaded %s", filename(path)); | ||
117 | return true; | ||
118 | } else { | ||
119 | set_status(vm, "load failed: %s", filename(path)); | ||
120 | return false; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static void print(BytePusher* vm, int x, int y, const char* str) { | ||
125 | SDL_SetRenderDrawColor(vm->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); | ||
126 | SDL_RenderDebugText(vm->renderer, (float)(x + 1), (float)(y + 1), str); | ||
127 | SDL_SetRenderDrawColor(vm->renderer, 0xff, 0xff, 0xff, SDL_ALPHA_OPAQUE); | ||
128 | SDL_RenderDebugText(vm->renderer, (float)x, (float)y, str); | ||
129 | SDL_SetRenderDrawColor(vm->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); | ||
130 | } | ||
131 | |||
132 | SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) { | ||
133 | BytePusher* vm; | ||
134 | SDL_Palette* palette; | ||
135 | SDL_Rect usable_bounds; | ||
136 | SDL_AudioSpec audiospec = { SDL_AUDIO_S8, 1, SAMPLES_PER_FRAME * FRAMES_PER_SECOND }; | ||
137 | SDL_DisplayID primary_display; | ||
138 | SDL_PropertiesID texprops; | ||
139 | int zoom = 2; | ||
140 | int i; | ||
141 | Uint8 r, g, b; | ||
142 | (void)argc; | ||
143 | (void)argv; | ||
144 | |||
145 | if (!SDL_SetAppMetadata("SDL 3 BytePusher", "1.0", "com.example.SDL3BytePusher")) { | ||
146 | return SDL_APP_FAILURE; | ||
147 | } | ||
148 | |||
149 | for (i = 0; i < (int)SDL_arraysize(extended_metadata); i++) { | ||
150 | if (!SDL_SetAppMetadataProperty(extended_metadata[i].key, extended_metadata[i].value)) { | ||
151 | return SDL_APP_FAILURE; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | if (!SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO)) { | ||
156 | return SDL_APP_FAILURE; | ||
157 | } | ||
158 | |||
159 | if (!(vm = (BytePusher *)SDL_calloc(1, sizeof(*vm)))) { | ||
160 | return SDL_APP_FAILURE; | ||
161 | } | ||
162 | *(BytePusher**)appstate = vm; | ||
163 | |||
164 | vm->display_help = true; | ||
165 | |||
166 | primary_display = SDL_GetPrimaryDisplay(); | ||
167 | if (SDL_GetDisplayUsableBounds(primary_display, &usable_bounds)) { | ||
168 | int zoom_w = (usable_bounds.w - usable_bounds.x) * 2 / 3 / SCREEN_W; | ||
169 | int zoom_h = (usable_bounds.h - usable_bounds.y) * 2 / 3 / SCREEN_H; | ||
170 | zoom = zoom_w < zoom_h ? zoom_w : zoom_h; | ||
171 | if (zoom < 1) { | ||
172 | zoom = 1; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if (!SDL_CreateWindowAndRenderer("SDL 3 BytePusher", | ||
177 | SCREEN_W * zoom, SCREEN_H * zoom, SDL_WINDOW_RESIZABLE, | ||
178 | &vm->window, &vm->renderer | ||
179 | )) { | ||
180 | return SDL_APP_FAILURE; | ||
181 | } | ||
182 | |||
183 | if (!SDL_SetRenderLogicalPresentation( | ||
184 | vm->renderer, SCREEN_W, SCREEN_H, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE | ||
185 | )) { | ||
186 | return SDL_APP_FAILURE; | ||
187 | } | ||
188 | |||
189 | if (!(vm->screen = SDL_CreateSurfaceFrom( | ||
190 | SCREEN_W, SCREEN_H, SDL_PIXELFORMAT_INDEX8, vm->screenbuf, SCREEN_W | ||
191 | ))) { | ||
192 | return SDL_APP_FAILURE; | ||
193 | } | ||
194 | |||
195 | if (!(palette = SDL_CreateSurfacePalette(vm->screen))) { | ||
196 | return SDL_APP_FAILURE; | ||
197 | } | ||
198 | i = 0; | ||
199 | for (r = 0; r < 6; ++r) { | ||
200 | for (g = 0; g < 6; ++g) { | ||
201 | for (b = 0; b < 6; ++b, ++i) { | ||
202 | SDL_Color color = { (Uint8)(r * 0x33), (Uint8)(g * 0x33), (Uint8)(b * 0x33), SDL_ALPHA_OPAQUE }; | ||
203 | palette->colors[i] = color; | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | for (; i < 256; ++i) { | ||
208 | SDL_Color color = { 0, 0, 0, SDL_ALPHA_OPAQUE }; | ||
209 | palette->colors[i] = color; | ||
210 | } | ||
211 | |||
212 | texprops = SDL_CreateProperties(); | ||
213 | SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STREAMING); | ||
214 | SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, SCREEN_W); | ||
215 | SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, SCREEN_H); | ||
216 | vm->screentex = SDL_CreateTextureWithProperties(vm->renderer, texprops); | ||
217 | SDL_SetNumberProperty(texprops, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_TARGET); | ||
218 | vm->rendertarget = SDL_CreateTextureWithProperties(vm->renderer, texprops); | ||
219 | SDL_DestroyProperties(texprops); | ||
220 | if (!vm->screentex || !vm->rendertarget) { | ||
221 | return SDL_APP_FAILURE; | ||
222 | } | ||
223 | SDL_SetTextureScaleMode(vm->screentex, SDL_SCALEMODE_NEAREST); | ||
224 | SDL_SetTextureScaleMode(vm->rendertarget, SDL_SCALEMODE_NEAREST); | ||
225 | |||
226 | if (!(vm->audiostream = SDL_OpenAudioDeviceStream( | ||
227 | SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audiospec, NULL, NULL | ||
228 | ))) { | ||
229 | return SDL_APP_FAILURE; | ||
230 | } | ||
231 | SDL_SetAudioStreamGain(vm->audiostream, 0.1f); /* examples are loud! */ | ||
232 | SDL_ResumeAudioStreamDevice(vm->audiostream); | ||
233 | |||
234 | set_status(vm, "renderer: %s", SDL_GetRendererName(vm->renderer)); | ||
235 | |||
236 | vm->last_tick = SDL_GetTicksNS(); | ||
237 | vm->tick_acc = NS_PER_SECOND; | ||
238 | |||
239 | return SDL_APP_CONTINUE; | ||
240 | } | ||
241 | |||
242 | SDL_AppResult SDL_AppIterate(void* appstate) { | ||
243 | BytePusher* vm = (BytePusher*)appstate; | ||
244 | |||
245 | Uint64 tick = SDL_GetTicksNS(); | ||
246 | Uint64 delta = tick - vm->last_tick; | ||
247 | bool updated, skip_audio; | ||
248 | |||
249 | vm->last_tick = tick; | ||
250 | |||
251 | vm->tick_acc += delta * FRAMES_PER_SECOND; | ||
252 | updated = vm->tick_acc >= NS_PER_SECOND; | ||
253 | skip_audio = vm->tick_acc >= MAX_AUDIO_LATENCY_FRAMES * NS_PER_SECOND; | ||
254 | |||
255 | if (skip_audio) { | ||
256 | // don't let audio fall too far behind | ||
257 | SDL_ClearAudioStream(vm->audiostream); | ||
258 | } | ||
259 | |||
260 | while (vm->tick_acc >= NS_PER_SECOND) { | ||
261 | Uint32 pc; | ||
262 | int i; | ||
263 | |||
264 | vm->tick_acc -= NS_PER_SECOND; | ||
265 | |||
266 | vm->ram[IO_KEYBOARD] = (Uint8)(vm->keystate >> 8); | ||
267 | vm->ram[IO_KEYBOARD + 1] = (Uint8)(vm->keystate); | ||
268 | |||
269 | pc = read_u24(vm, IO_PC); | ||
270 | for (i = 0; i < SCREEN_W * SCREEN_H; ++i) { | ||
271 | Uint32 src = read_u24(vm, pc); | ||
272 | Uint32 dst = read_u24(vm, pc + 3); | ||
273 | vm->ram[dst] = vm->ram[src]; | ||
274 | pc = read_u24(vm, pc + 6); | ||
275 | } | ||
276 | |||
277 | if (!skip_audio || vm->tick_acc < NS_PER_SECOND) { | ||
278 | SDL_PutAudioStreamData( | ||
279 | vm->audiostream, | ||
280 | &vm->ram[(Uint32)read_u16(vm, IO_AUDIO_BANK) << 8], | ||
281 | SAMPLES_PER_FRAME | ||
282 | ); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | if (updated) { | ||
287 | SDL_Surface *tex; | ||
288 | |||
289 | SDL_SetRenderTarget(vm->renderer, vm->rendertarget); | ||
290 | |||
291 | if (!SDL_LockTextureToSurface(vm->screentex, NULL, &tex)) { | ||
292 | return SDL_APP_FAILURE; | ||
293 | } | ||
294 | vm->screen->pixels = &vm->ram[(Uint32)vm->ram[IO_SCREEN_PAGE] << 16]; | ||
295 | SDL_BlitSurface(vm->screen, NULL, tex, NULL); | ||
296 | SDL_UnlockTexture(vm->screentex); | ||
297 | |||
298 | SDL_RenderTexture(vm->renderer, vm->screentex, NULL, NULL); | ||
299 | } | ||
300 | |||
301 | if (vm->display_help) { | ||
302 | print(vm, 4, 4, "Drop a BytePusher file in this"); | ||
303 | print(vm, 8, 12, "window to load and run it!"); | ||
304 | print(vm, 4, 28, "Press ENTER to switch between"); | ||
305 | print(vm, 8, 36, "positional and symbolic input."); | ||
306 | } | ||
307 | |||
308 | if (vm->status_ticks > 0) { | ||
309 | vm->status_ticks -= 1; | ||
310 | print(vm, 4, SCREEN_H - 12, vm->status); | ||
311 | } | ||
312 | |||
313 | SDL_SetRenderTarget(vm->renderer, NULL); | ||
314 | SDL_RenderClear(vm->renderer); | ||
315 | SDL_RenderTexture(vm->renderer, vm->rendertarget, NULL, NULL); | ||
316 | SDL_RenderPresent(vm->renderer); | ||
317 | |||
318 | return SDL_APP_CONTINUE; | ||
319 | } | ||
320 | |||
321 | static Uint16 keycode_mask(SDL_Keycode key) { | ||
322 | int index; | ||
323 | if (key >= SDLK_0 && key <= SDLK_9) { | ||
324 | index = key - SDLK_0; | ||
325 | } else if (key >= SDLK_A && key <= SDLK_F) { | ||
326 | index = key - SDLK_A + 10; | ||
327 | } else { | ||
328 | return 0; | ||
329 | } | ||
330 | return (Uint16)1 << index; | ||
331 | } | ||
332 | |||
333 | static Uint16 scancode_mask(SDL_Scancode scancode) { | ||
334 | int index; | ||
335 | switch (scancode) { | ||
336 | case SDL_SCANCODE_1: index = 0x1; break; | ||
337 | case SDL_SCANCODE_2: index = 0x2; break; | ||
338 | case SDL_SCANCODE_3: index = 0x3; break; | ||
339 | case SDL_SCANCODE_4: index = 0xc; break; | ||
340 | case SDL_SCANCODE_Q: index = 0x4; break; | ||
341 | case SDL_SCANCODE_W: index = 0x5; break; | ||
342 | case SDL_SCANCODE_E: index = 0x6; break; | ||
343 | case SDL_SCANCODE_R: index = 0xd; break; | ||
344 | case SDL_SCANCODE_A: index = 0x7; break; | ||
345 | case SDL_SCANCODE_S: index = 0x8; break; | ||
346 | case SDL_SCANCODE_D: index = 0x9; break; | ||
347 | case SDL_SCANCODE_F: index = 0xe; break; | ||
348 | case SDL_SCANCODE_Z: index = 0xa; break; | ||
349 | case SDL_SCANCODE_X: index = 0x0; break; | ||
350 | case SDL_SCANCODE_C: index = 0xb; break; | ||
351 | case SDL_SCANCODE_V: index = 0xf; break; | ||
352 | default: return 0; | ||
353 | } | ||
354 | return (Uint16)1 << index; | ||
355 | } | ||
356 | |||
357 | SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) { | ||
358 | BytePusher* vm = (BytePusher*)appstate; | ||
359 | |||
360 | switch (event->type) { | ||
361 | case SDL_EVENT_QUIT: | ||
362 | return SDL_APP_SUCCESS; | ||
363 | |||
364 | case SDL_EVENT_DROP_FILE: | ||
365 | load_file(vm, event->drop.data); | ||
366 | break; | ||
367 | |||
368 | case SDL_EVENT_KEY_DOWN: | ||
369 | #ifndef __EMSCRIPTEN__ | ||
370 | if (event->key.key == SDLK_ESCAPE) { | ||
371 | return SDL_APP_SUCCESS; | ||
372 | } | ||
373 | #endif | ||
374 | if (event->key.key == SDLK_RETURN) { | ||
375 | vm->positional_input = !vm->positional_input; | ||
376 | vm->keystate = 0; | ||
377 | if (vm->positional_input) { | ||
378 | set_status(vm, "switched to positional input"); | ||
379 | } else { | ||
380 | set_status(vm, "switched to symbolic input"); | ||
381 | } | ||
382 | } | ||
383 | if (vm->positional_input) { | ||
384 | vm->keystate |= scancode_mask(event->key.scancode); | ||
385 | } else { | ||
386 | vm->keystate |= keycode_mask(event->key.key); | ||
387 | } | ||
388 | break; | ||
389 | |||
390 | case SDL_EVENT_KEY_UP: | ||
391 | if (vm->positional_input) { | ||
392 | vm->keystate &= ~scancode_mask(event->key.scancode); | ||
393 | } else { | ||
394 | vm->keystate &= ~keycode_mask(event->key.key); | ||
395 | } | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | return SDL_APP_CONTINUE; | ||
400 | } | ||
401 | |||
402 | void SDL_AppQuit(void* appstate, SDL_AppResult result) { | ||
403 | if (result == SDL_APP_FAILURE) { | ||
404 | SDL_Log("Error: %s", SDL_GetError()); | ||
405 | } | ||
406 | if (appstate) { | ||
407 | BytePusher* vm = (BytePusher*)appstate; | ||
408 | SDL_DestroyAudioStream(vm->audiostream); | ||
409 | SDL_DestroyTexture(vm->rendertarget); | ||
410 | SDL_DestroyTexture(vm->screentex); | ||
411 | SDL_DestroySurface(vm->screen); | ||
412 | SDL_DestroyRenderer(vm->renderer); | ||
413 | SDL_DestroyWindow(vm->window); | ||
414 | SDL_free(vm); | ||
415 | } | ||
416 | } | ||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/onmouseover.webp new file mode 100644 index 0000000..b99e7dd --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/thumbnail.png b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/thumbnail.png new file mode 100644 index 0000000..891aa8f --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/04-bytepusher/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/demo/description.txt b/src/contrib/SDL-3.2.20/examples/demo/description.txt new file mode 100644 index 0000000..77bcbb7 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/demo/description.txt | |||
@@ -0,0 +1 @@ | |||
Full game and app demos \ No newline at end of file | |||
diff --git a/src/contrib/SDL-3.2.20/examples/highlight-plugin.lua b/src/contrib/SDL-3.2.20/examples/highlight-plugin.lua new file mode 100644 index 0000000..9598ec9 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/highlight-plugin.lua | |||
@@ -0,0 +1,79 @@ | |||
1 | -- This code adapted from https://gitlab.com/saalen/highlight/-/wikis/Plug-Ins | ||
2 | |||
3 | -- first add a description of what the plug-in does | ||
4 | Description="Add wiki.libsdl.org reference links to HTML, LaTeX or RTF output" | ||
5 | |||
6 | -- define the plugin categories (ie. supported output formats; languages) | ||
7 | Categories = { "c", "c++" } | ||
8 | |||
9 | -- the syntaxUpdate function contains code related to syntax recognition | ||
10 | function syntaxUpdate(desc) | ||
11 | |||
12 | -- if the current file is not C/C++ file we exit | ||
13 | if desc~="C and C++" then | ||
14 | return | ||
15 | end | ||
16 | |||
17 | -- this function returns a qt-project reference link of the given token | ||
18 | function getURL(token) | ||
19 | -- generate the URL | ||
20 | url='https://wiki.libsdl.org/SDL3/'.. token | ||
21 | |||
22 | -- embed the URL in a hyperlink according to the output format | ||
23 | -- first HTML, then LaTeX and RTF | ||
24 | if (HL_OUTPUT== HL_FORMAT_HTML or HL_OUTPUT == HL_FORMAT_XHTML) then | ||
25 | return '<a class="hl" target="new" href="' | ||
26 | .. url .. '">'.. token .. '</a>' | ||
27 | elseif (HL_OUTPUT == HL_FORMAT_LATEX) then | ||
28 | return '\\href{'..url..'}{'..token..'}' | ||
29 | elseif (HL_OUTPUT == HL_FORMAT_RTF) then | ||
30 | return '{{\\field{\\*\\fldinst HYPERLINK "' | ||
31 | ..url..'" }{\\fldrslt\\ul\\ulc0 '..token..'}}}' | ||
32 | end | ||
33 | end | ||
34 | |||
35 | -- the Decorate function will be invoked for every recognized token | ||
36 | function Decorate(token, state) | ||
37 | |||
38 | -- we are only interested in keywords, preprocessor or default items | ||
39 | if (state ~= HL_STANDARD and state ~= HL_KEYWORD and | ||
40 | state ~=HL_PREPROC) then | ||
41 | return | ||
42 | end | ||
43 | |||
44 | -- SDL keywords start with SDL_ | ||
45 | -- if this pattern applies to the token, we return the URL | ||
46 | -- if we return nothing, the token is outputted as is | ||
47 | if ( (token == "Uint8") or (token == "Uint16") or (token == "Uint32") or (token == "Uint64") or | ||
48 | (token == "Sint8") or (token == "Sint16") or (token == "Sint32") or (token == "Sint64") or | ||
49 | (string.find(token, "SDL_") == 1) ) then | ||
50 | return getURL(token) | ||
51 | end | ||
52 | |||
53 | end | ||
54 | end | ||
55 | |||
56 | -- the themeUpdate function contains code related to the theme | ||
57 | function themeUpdate(desc) | ||
58 | -- the Injections table can be used to add style information to the theme | ||
59 | |||
60 | -- HTML: we add additional CSS style information to beautify hyperlinks, | ||
61 | -- they should have the same color as their surrounding tags | ||
62 | if (HL_OUTPUT == HL_FORMAT_HTML or HL_OUTPUT == HL_FORMAT_XHTML) then | ||
63 | Injections[#Injections+1]= | ||
64 | "a.hl, a.hl:visited {color:inherit;font-weight:inherit;text-decoration:none}" | ||
65 | |||
66 | -- LaTeX: hyperlinks require the hyperref package, so we add this here | ||
67 | -- the colorlinks and pdfborderstyle options remove ugly boxes in the output | ||
68 | elseif (HL_OUTPUT==HL_FORMAT_LATEX) then | ||
69 | Injections[#Injections+1]= | ||
70 | "\\usepackage[colorlinks=false, pdfborderstyle={/S/U/W 1}]{hyperref}" | ||
71 | end | ||
72 | end | ||
73 | |||
74 | -- let highlight load the chunks | ||
75 | Plugins={ | ||
76 | { Type="lang", Chunk=syntaxUpdate }, | ||
77 | { Type="theme", Chunk=themeUpdate }, | ||
78 | } | ||
79 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/README.txt b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/README.txt new file mode 100644 index 0000000..89e2bee --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/README.txt | |||
@@ -0,0 +1,2 @@ | |||
1 | This example code looks for the current joystick state once per frame, | ||
2 | and draws a visual representation of it. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/joystick-polling.c b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/joystick-polling.c new file mode 100644 index 0000000..6eb23b8 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/joystick-polling.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * This example code looks for the current joystick state once per frame, | ||
3 | * and draws a visual representation of it. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | /* Joysticks are low-level interfaces: there's something with a bunch of | ||
9 | buttons, axes and hats, in no understood order or position. This is | ||
10 | a flexible interface, but you'll need to build some sort of configuration | ||
11 | UI to let people tell you what button, etc, does what. On top of this | ||
12 | interface, SDL offers the "gamepad" API, which works with lots of devices, | ||
13 | and knows how to map arbitrary buttons and such to look like an | ||
14 | Xbox/PlayStation/etc gamepad. This is easier, and better, for many games, | ||
15 | but isn't necessarily a good fit for complex apps and hardware. A flight | ||
16 | simulator, a realistic racing game, etc, might want this interface instead | ||
17 | of gamepads. */ | ||
18 | |||
19 | /* SDL can handle multiple joysticks, but for simplicity, this program only | ||
20 | deals with the first stick it sees. */ | ||
21 | |||
22 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
23 | #include <SDL3/SDL.h> | ||
24 | #include <SDL3/SDL_main.h> | ||
25 | |||
26 | /* We will use this renderer to draw into this window every frame. */ | ||
27 | static SDL_Window *window = NULL; | ||
28 | static SDL_Renderer *renderer = NULL; | ||
29 | static SDL_Joystick *joystick = NULL; | ||
30 | static SDL_Color colors[64]; | ||
31 | |||
32 | /* This function runs once at startup. */ | ||
33 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
34 | { | ||
35 | int i; | ||
36 | |||
37 | SDL_SetAppMetadata("Example Input Joystick Polling", "1.0", "com.example.input-joystick-polling"); | ||
38 | |||
39 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)) { | ||
40 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
41 | return SDL_APP_FAILURE; | ||
42 | } | ||
43 | |||
44 | if (!SDL_CreateWindowAndRenderer("examples/input/joystick-polling", 640, 480, 0, &window, &renderer)) { | ||
45 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
46 | return SDL_APP_FAILURE; | ||
47 | } | ||
48 | |||
49 | for (i = 0; i < SDL_arraysize(colors); i++) { | ||
50 | colors[i].r = SDL_rand(255); | ||
51 | colors[i].g = SDL_rand(255); | ||
52 | colors[i].b = SDL_rand(255); | ||
53 | colors[i].a = 255; | ||
54 | } | ||
55 | |||
56 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
57 | } | ||
58 | |||
59 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
60 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
61 | { | ||
62 | if (event->type == SDL_EVENT_QUIT) { | ||
63 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
64 | } else if (event->type == SDL_EVENT_JOYSTICK_ADDED) { | ||
65 | /* this event is sent for each hotplugged stick, but also each already-connected joystick during SDL_Init(). */ | ||
66 | if (joystick == NULL) { /* we don't have a stick yet and one was added, open it! */ | ||
67 | joystick = SDL_OpenJoystick(event->jdevice.which); | ||
68 | if (!joystick) { | ||
69 | SDL_Log("Failed to open joystick ID %u: %s", (unsigned int) event->jdevice.which, SDL_GetError()); | ||
70 | } | ||
71 | } | ||
72 | } else if (event->type == SDL_EVENT_JOYSTICK_REMOVED) { | ||
73 | if (joystick && (SDL_GetJoystickID(joystick) == event->jdevice.which)) { | ||
74 | SDL_CloseJoystick(joystick); /* our joystick was unplugged. */ | ||
75 | joystick = NULL; | ||
76 | } | ||
77 | } | ||
78 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
79 | } | ||
80 | |||
81 | /* This function runs once per frame, and is the heart of the program. */ | ||
82 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
83 | { | ||
84 | int winw = 640, winh = 480; | ||
85 | const char *text = "Plug in a joystick, please."; | ||
86 | float x, y; | ||
87 | int i; | ||
88 | |||
89 | if (joystick) { /* we have a stick opened? */ | ||
90 | text = SDL_GetJoystickName(joystick); | ||
91 | } | ||
92 | |||
93 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
94 | SDL_RenderClear(renderer); | ||
95 | SDL_GetWindowSize(window, &winw, &winh); | ||
96 | |||
97 | /* note that you can get input as events, instead of polling, which is | ||
98 | better since it won't miss button presses if the system is lagging, | ||
99 | but often times checking the current state per-frame is good enough, | ||
100 | and maybe better if you'd rather _drop_ inputs due to lag. */ | ||
101 | |||
102 | if (joystick) { /* we have a stick opened? */ | ||
103 | const float size = 30.0f; | ||
104 | int total; | ||
105 | |||
106 | /* 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. */ | ||
107 | total = SDL_GetNumJoystickAxes(joystick); | ||
108 | y = (winh - (total * size)) / 2; | ||
109 | x = ((float) winw) / 2.0f; | ||
110 | for (i = 0; i < total; i++) { | ||
111 | const SDL_Color *color = &colors[i % SDL_arraysize(colors)]; | ||
112 | const float val = (((float) SDL_GetJoystickAxis(joystick, i)) / 32767.0f); /* make it -1.0f to 1.0f */ | ||
113 | const float dx = x + (val * x); | ||
114 | const SDL_FRect dst = { dx, y, x - SDL_fabsf(dx), size }; | ||
115 | SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, color->a); | ||
116 | SDL_RenderFillRect(renderer, &dst); | ||
117 | y += size; | ||
118 | } | ||
119 | |||
120 | /* draw buttons as blocks across top of window. We only know the button numbers, but not where they are on the device. */ | ||
121 | total = SDL_GetNumJoystickButtons(joystick); | ||
122 | x = (winw - (total * size)) / 2; | ||
123 | for (i = 0; i < total; i++) { | ||
124 | const SDL_Color *color = &colors[i % SDL_arraysize(colors)]; | ||
125 | const SDL_FRect dst = { x, 0.0f, size, size }; | ||
126 | if (SDL_GetJoystickButton(joystick, i)) { | ||
127 | SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, color->a); | ||
128 | } else { | ||
129 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
130 | } | ||
131 | SDL_RenderFillRect(renderer, &dst); | ||
132 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, color->a); | ||
133 | SDL_RenderRect(renderer, &dst); /* outline it */ | ||
134 | x += size; | ||
135 | } | ||
136 | |||
137 | /* draw hats across the bottom of the screen. */ | ||
138 | total = SDL_GetNumJoystickHats(joystick); | ||
139 | x = ((winw - (total * (size * 2.0f))) / 2.0f) + (size / 2.0f); | ||
140 | y = ((float) winh) - size; | ||
141 | for (i = 0; i < total; i++) { | ||
142 | const SDL_Color *color = &colors[i % SDL_arraysize(colors)]; | ||
143 | const float thirdsize = size / 3.0f; | ||
144 | const SDL_FRect cross[] = { { x, y + thirdsize, size, thirdsize }, { x + thirdsize, y, thirdsize, size } }; | ||
145 | const Uint8 hat = SDL_GetJoystickHat(joystick, i); | ||
146 | |||
147 | SDL_SetRenderDrawColor(renderer, 90, 90, 90, 255); | ||
148 | SDL_RenderFillRects(renderer, cross, SDL_arraysize(cross)); | ||
149 | |||
150 | SDL_SetRenderDrawColor(renderer, color->r, color->g, color->b, color->a); | ||
151 | |||
152 | if (hat & SDL_HAT_UP) { | ||
153 | const SDL_FRect dst = { x + thirdsize, y, thirdsize, thirdsize }; | ||
154 | SDL_RenderFillRect(renderer, &dst); | ||
155 | } | ||
156 | |||
157 | if (hat & SDL_HAT_RIGHT) { | ||
158 | const SDL_FRect dst = { x + (thirdsize * 2), y + thirdsize, thirdsize, thirdsize }; | ||
159 | SDL_RenderFillRect(renderer, &dst); | ||
160 | } | ||
161 | |||
162 | if (hat & SDL_HAT_DOWN) { | ||
163 | const SDL_FRect dst = { x + thirdsize, y + (thirdsize * 2), thirdsize, thirdsize }; | ||
164 | SDL_RenderFillRect(renderer, &dst); | ||
165 | } | ||
166 | |||
167 | if (hat & SDL_HAT_LEFT) { | ||
168 | const SDL_FRect dst = { x, y + thirdsize, thirdsize, thirdsize }; | ||
169 | SDL_RenderFillRect(renderer, &dst); | ||
170 | } | ||
171 | |||
172 | x += size * 2; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | x = (((float) winw) - (SDL_strlen(text) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE)) / 2.0f; | ||
177 | y = (((float) winh) - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) / 2.0f; | ||
178 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
179 | SDL_RenderDebugText(renderer, x, y, text); | ||
180 | SDL_RenderPresent(renderer); | ||
181 | |||
182 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
183 | } | ||
184 | |||
185 | /* This function runs once at shutdown. */ | ||
186 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
187 | { | ||
188 | if (joystick) { | ||
189 | SDL_CloseJoystick(joystick); | ||
190 | } | ||
191 | |||
192 | /* SDL will clean up the window/renderer for us. */ | ||
193 | } | ||
diff --git a/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/onmouseover.webp new file mode 100644 index 0000000..484539c --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/thumbnail.png b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/thumbnail.png new file mode 100644 index 0000000..4faebba --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/01-joystick-polling/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/README.txt b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/README.txt new file mode 100644 index 0000000..d87ac0a --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/README.txt | |||
@@ -0,0 +1,2 @@ | |||
1 | This example code looks for joystick input in the event handler, and | ||
2 | reports any changes as a flood of info. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/joystick-events.c b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/joystick-events.c new file mode 100644 index 0000000..cc01d84 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/joystick-events.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * This example code looks for joystick input in the event handler, and | ||
3 | * reports any changes as a flood of info. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | /* Joysticks are low-level interfaces: there's something with a bunch of | ||
9 | buttons, axes and hats, in no understood order or position. This is | ||
10 | a flexible interface, but you'll need to build some sort of configuration | ||
11 | UI to let people tell you what button, etc, does what. On top of this | ||
12 | interface, SDL offers the "gamepad" API, which works with lots of devices, | ||
13 | and knows how to map arbitrary buttons and such to look like an | ||
14 | Xbox/PlayStation/etc gamepad. This is easier, and better, for many games, | ||
15 | but isn't necessarily a good fit for complex apps and hardware. A flight | ||
16 | simulator, a realistic racing game, etc, might want this interface instead | ||
17 | of gamepads. */ | ||
18 | |||
19 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
20 | #include <SDL3/SDL.h> | ||
21 | #include <SDL3/SDL_main.h> | ||
22 | |||
23 | /* We will use this renderer to draw into this window every frame. */ | ||
24 | static SDL_Window *window = NULL; | ||
25 | static SDL_Renderer *renderer = NULL; | ||
26 | static SDL_Color colors[64]; | ||
27 | |||
28 | #define MOTION_EVENT_COOLDOWN 40 | ||
29 | |||
30 | typedef struct EventMessage | ||
31 | { | ||
32 | char *str; | ||
33 | SDL_Color color; | ||
34 | Uint64 start_ticks; | ||
35 | struct EventMessage *next; | ||
36 | } EventMessage; | ||
37 | |||
38 | static EventMessage messages; | ||
39 | static EventMessage *messages_tail = &messages; | ||
40 | |||
41 | static const char *hat_state_string(Uint8 state) | ||
42 | { | ||
43 | switch (state) { | ||
44 | case SDL_HAT_CENTERED: return "CENTERED"; | ||
45 | case SDL_HAT_UP: return "UP"; | ||
46 | case SDL_HAT_RIGHT: return "RIGHT"; | ||
47 | case SDL_HAT_DOWN: return "DOWN"; | ||
48 | case SDL_HAT_LEFT: return "LEFT"; | ||
49 | case SDL_HAT_RIGHTUP: return "RIGHT+UP"; | ||
50 | case SDL_HAT_RIGHTDOWN: return "RIGHT+DOWN"; | ||
51 | case SDL_HAT_LEFTUP: return "LEFT+UP"; | ||
52 | case SDL_HAT_LEFTDOWN: return "LEFT+DOWN"; | ||
53 | default: break; | ||
54 | } | ||
55 | return "UNKNOWN"; | ||
56 | } | ||
57 | |||
58 | static const char *battery_state_string(SDL_PowerState state) | ||
59 | { | ||
60 | switch (state) { | ||
61 | case SDL_POWERSTATE_ERROR: return "ERROR"; | ||
62 | case SDL_POWERSTATE_UNKNOWN: return "UNKNOWN"; | ||
63 | case SDL_POWERSTATE_ON_BATTERY: return "ON BATTERY"; | ||
64 | case SDL_POWERSTATE_NO_BATTERY: return "NO BATTERY"; | ||
65 | case SDL_POWERSTATE_CHARGING: return "CHARGING"; | ||
66 | case SDL_POWERSTATE_CHARGED: return "CHARGED"; | ||
67 | default: break; | ||
68 | } | ||
69 | return "UNKNOWN"; | ||
70 | } | ||
71 | |||
72 | static void add_message(SDL_JoystickID jid, const char *fmt, ...) | ||
73 | { | ||
74 | const SDL_Color *color = &colors[((size_t) jid) % SDL_arraysize(colors)]; | ||
75 | EventMessage *msg = NULL; | ||
76 | char *str = NULL; | ||
77 | va_list ap; | ||
78 | |||
79 | msg = (EventMessage *) SDL_calloc(1, sizeof (*msg)); | ||
80 | if (!msg) { | ||
81 | return; // oh well. | ||
82 | } | ||
83 | |||
84 | va_start(ap, fmt); | ||
85 | SDL_vasprintf(&str, fmt, ap); | ||
86 | va_end(ap); | ||
87 | if (!str) { | ||
88 | SDL_free(msg); | ||
89 | return; // oh well. | ||
90 | } | ||
91 | |||
92 | msg->str = str; | ||
93 | SDL_copyp(&msg->color, color); | ||
94 | msg->start_ticks = SDL_GetTicks(); | ||
95 | msg->next = NULL; | ||
96 | |||
97 | messages_tail->next = msg; | ||
98 | messages_tail = msg; | ||
99 | } | ||
100 | |||
101 | |||
102 | /* This function runs once at startup. */ | ||
103 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
104 | { | ||
105 | int i; | ||
106 | |||
107 | SDL_SetAppMetadata("Example Input Joystick Events", "1.0", "com.example.input-joystick-events"); | ||
108 | |||
109 | if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)) { | ||
110 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
111 | return SDL_APP_FAILURE; | ||
112 | } | ||
113 | |||
114 | if (!SDL_CreateWindowAndRenderer("examples/input/joystick-events", 640, 480, 0, &window, &renderer)) { | ||
115 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
116 | return SDL_APP_FAILURE; | ||
117 | } | ||
118 | |||
119 | colors[0].r = colors[0].g = colors[0].b = colors[0].a = 255; | ||
120 | for (i = 1; i < SDL_arraysize(colors); i++) { | ||
121 | colors[i].r = SDL_rand(255); | ||
122 | colors[i].g = SDL_rand(255); | ||
123 | colors[i].b = SDL_rand(255); | ||
124 | colors[i].a = 255; | ||
125 | } | ||
126 | |||
127 | add_message(0, "Please plug in a joystick."); | ||
128 | |||
129 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
130 | } | ||
131 | |||
132 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
133 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
134 | { | ||
135 | if (event->type == SDL_EVENT_QUIT) { | ||
136 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
137 | } else if (event->type == SDL_EVENT_JOYSTICK_ADDED) { | ||
138 | /* this event is sent for each hotplugged stick, but also each already-connected joystick during SDL_Init(). */ | ||
139 | const SDL_JoystickID which = event->jdevice.which; | ||
140 | SDL_Joystick *joystick = SDL_OpenJoystick(which); | ||
141 | if (!joystick) { | ||
142 | add_message(which, "Joystick #%u add, but not opened: %s", (unsigned int) which, SDL_GetError()); | ||
143 | } else { | ||
144 | add_message(which, "Joystick #%u ('%s') added", (unsigned int) which, SDL_GetJoystickName(joystick)); | ||
145 | } | ||
146 | } else if (event->type == SDL_EVENT_JOYSTICK_REMOVED) { | ||
147 | const SDL_JoystickID which = event->jdevice.which; | ||
148 | SDL_Joystick *joystick = SDL_GetJoystickFromID(which); | ||
149 | if (joystick) { | ||
150 | SDL_CloseJoystick(joystick); /* the joystick was unplugged. */ | ||
151 | } | ||
152 | add_message(which, "Joystick #%u removed", (unsigned int) which); | ||
153 | } else if (event->type == SDL_EVENT_JOYSTICK_AXIS_MOTION) { | ||
154 | static Uint64 axis_motion_cooldown_time = 0; /* these are spammy, only show every X milliseconds. */ | ||
155 | const Uint64 now = SDL_GetTicks(); | ||
156 | if (now >= axis_motion_cooldown_time) { | ||
157 | const SDL_JoystickID which = event->jaxis.which; | ||
158 | axis_motion_cooldown_time = now + MOTION_EVENT_COOLDOWN; | ||
159 | add_message(which, "Joystick #%u axis %d -> %d", (unsigned int) which, (int) event->jaxis.axis, (int) event->jaxis.value); | ||
160 | } | ||
161 | } else if (event->type == SDL_EVENT_JOYSTICK_BALL_MOTION) { | ||
162 | static Uint64 ball_motion_cooldown_time = 0; /* these are spammy, only show every X milliseconds. */ | ||
163 | const Uint64 now = SDL_GetTicks(); | ||
164 | if (now >= ball_motion_cooldown_time) { | ||
165 | const SDL_JoystickID which = event->jball.which; | ||
166 | ball_motion_cooldown_time = now + MOTION_EVENT_COOLDOWN; | ||
167 | add_message(which, "Joystick #%u ball %d -> %d, %d", (unsigned int) which, (int) event->jball.ball, (int) event->jball.xrel, (int) event->jball.yrel); | ||
168 | } | ||
169 | } else if (event->type == SDL_EVENT_JOYSTICK_HAT_MOTION) { | ||
170 | const SDL_JoystickID which = event->jhat.which; | ||
171 | add_message(which, "Joystick #%u hat %d -> %s", (unsigned int) which, (int) event->jhat.hat, hat_state_string(event->jhat.value)); | ||
172 | } else if ((event->type == SDL_EVENT_JOYSTICK_BUTTON_UP) || (event->type == SDL_EVENT_JOYSTICK_BUTTON_DOWN)) { | ||
173 | const SDL_JoystickID which = event->jbutton.which; | ||
174 | add_message(which, "Joystick #%u button %d -> %s", (unsigned int) which, (int) event->jbutton.button, event->jbutton.down ? "PRESSED" : "RELEASED"); | ||
175 | } else if (event->type == SDL_EVENT_JOYSTICK_BATTERY_UPDATED) { | ||
176 | const SDL_JoystickID which = event->jbattery.which; | ||
177 | add_message(which, "Joystick #%u battery -> %s - %d%%", (unsigned int) which, battery_state_string(event->jbattery.state), event->jbattery.percent); | ||
178 | } | ||
179 | |||
180 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
181 | } | ||
182 | |||
183 | /* This function runs once per frame, and is the heart of the program. */ | ||
184 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
185 | { | ||
186 | const Uint64 now = SDL_GetTicks(); | ||
187 | const float msg_lifetime = 3500.0f; /* milliseconds a message lives for. */ | ||
188 | EventMessage *msg = messages.next; | ||
189 | float prev_y = 0.0f; | ||
190 | int winw = 640, winh = 480; | ||
191 | |||
192 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | ||
193 | SDL_RenderClear(renderer); | ||
194 | SDL_GetWindowSize(window, &winw, &winh); | ||
195 | |||
196 | while (msg) { | ||
197 | float x, y; | ||
198 | const float life_percent = ((float) (now - msg->start_ticks)) / msg_lifetime; | ||
199 | if (life_percent >= 1.0f) { /* msg is done. */ | ||
200 | messages.next = msg->next; | ||
201 | if (messages_tail == msg) { | ||
202 | messages_tail = &messages; | ||
203 | } | ||
204 | SDL_free(msg->str); | ||
205 | SDL_free(msg); | ||
206 | msg = messages.next; | ||
207 | continue; | ||
208 | } | ||
209 | x = (((float) winw) - (SDL_strlen(msg->str) * SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE)) / 2.0f; | ||
210 | y = ((float) winh) * life_percent; | ||
211 | if ((prev_y != 0.0f) && ((prev_y - y) < ((float) SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE))) { | ||
212 | msg->start_ticks = now; | ||
213 | break; // wait for the previous message to tick up a little. | ||
214 | } | ||
215 | |||
216 | SDL_SetRenderDrawColor(renderer, msg->color.r, msg->color.g, msg->color.b, (Uint8) (((float) msg->color.a) * (1.0f - life_percent))); | ||
217 | SDL_RenderDebugText(renderer, x, y, msg->str); | ||
218 | |||
219 | prev_y = y; | ||
220 | msg = msg->next; | ||
221 | } | ||
222 | |||
223 | SDL_RenderPresent(renderer); | ||
224 | |||
225 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
226 | } | ||
227 | |||
228 | /* This function runs once at shutdown. */ | ||
229 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
230 | { | ||
231 | /* SDL will clean up the window/renderer for us. We let the joysticks leak. */ | ||
232 | } | ||
diff --git a/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/onmouseover.webp new file mode 100644 index 0000000..05a9b42 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/thumbnail.png b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/thumbnail.png new file mode 100644 index 0000000..07f3ff1 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/input/02-joystick-events/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/README.txt b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/README.txt new file mode 100644 index 0000000..693cda8 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | You need something with a pen/stylus for this to work. | ||
2 | |||
3 | This takes pen input and draws lines. Lines are darker when you press harder. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/drawing-lines.c b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/drawing-lines.c new file mode 100644 index 0000000..d0d78ea --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/drawing-lines.c | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * This example code reads pen/stylus input and draws lines. Darker lines | ||
3 | * for harder pressure. | ||
4 | * | ||
5 | * SDL can track multiple pens, but for simplicity here, this assumes any | ||
6 | * pen input we see was from one device. | ||
7 | * | ||
8 | * This code is public domain. Feel free to use it for any purpose! | ||
9 | */ | ||
10 | |||
11 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
12 | #include <SDL3/SDL.h> | ||
13 | #include <SDL3/SDL_main.h> | ||
14 | |||
15 | /* We will use this renderer to draw into this window every frame. */ | ||
16 | static SDL_Window *window = NULL; | ||
17 | static SDL_Renderer *renderer = NULL; | ||
18 | static SDL_Texture *render_target = NULL; | ||
19 | static float pressure = 0.0f; | ||
20 | static float previous_touch_x = -1.0f; | ||
21 | static float previous_touch_y = -1.0f; | ||
22 | static float tilt_x = 0.0f; | ||
23 | static float tilt_y = 0.0f; | ||
24 | |||
25 | /* This function runs once at startup. */ | ||
26 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
27 | { | ||
28 | int w, h; | ||
29 | |||
30 | SDL_SetAppMetadata("Example Pen Drawing Lines", "1.0", "com.example.pen-drawing-lines"); | ||
31 | |||
32 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
33 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
34 | return SDL_APP_FAILURE; | ||
35 | } | ||
36 | |||
37 | if (!SDL_CreateWindowAndRenderer("examples/pen/drawing-lines", 640, 480, 0, &window, &renderer)) { | ||
38 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
39 | return SDL_APP_FAILURE; | ||
40 | } | ||
41 | |||
42 | /* we make a render target so we can draw lines to it and not have to record and redraw every pen stroke each frame. | ||
43 | Instead rendering a frame for us is a single texture draw. */ | ||
44 | |||
45 | /* make sure the render target matches output size (for hidpi displays, etc) so drawing matches the pen's position on a tablet display. */ | ||
46 | SDL_GetRenderOutputSize(renderer, &w, &h); | ||
47 | render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h); | ||
48 | if (!render_target) { | ||
49 | SDL_Log("Couldn't create render target: %s", SDL_GetError()); | ||
50 | return SDL_APP_FAILURE; | ||
51 | } | ||
52 | |||
53 | /* just blank the render target to gray to start. */ | ||
54 | SDL_SetRenderTarget(renderer, render_target); | ||
55 | SDL_SetRenderDrawColor(renderer, 100, 100, 100, SDL_ALPHA_OPAQUE); | ||
56 | SDL_RenderClear(renderer); | ||
57 | SDL_SetRenderTarget(renderer, NULL); | ||
58 | SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); | ||
59 | |||
60 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
61 | } | ||
62 | |||
63 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
64 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
65 | { | ||
66 | if (event->type == SDL_EVENT_QUIT) { | ||
67 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
68 | } | ||
69 | |||
70 | /* There are several events that track the specific stages of pen activity, | ||
71 | but we're only going to look for motion and pressure, for simplicity. */ | ||
72 | if (event->type == SDL_EVENT_PEN_MOTION) { | ||
73 | /* you can check for when the pen is touching, but if pressure > 0.0f, it's definitely touching! */ | ||
74 | if (pressure > 0.0f) { | ||
75 | if (previous_touch_x >= 0.0f) { /* only draw if we're moving while touching */ | ||
76 | /* draw with the alpha set to the pressure, so you effectively get a fainter line for lighter presses. */ | ||
77 | SDL_SetRenderTarget(renderer, render_target); | ||
78 | SDL_SetRenderDrawColorFloat(renderer, 0, 0, 0, pressure); | ||
79 | SDL_RenderLine(renderer, previous_touch_x, previous_touch_y, event->pmotion.x, event->pmotion.y); | ||
80 | } | ||
81 | previous_touch_x = event->pmotion.x; | ||
82 | previous_touch_y = event->pmotion.y; | ||
83 | } else { | ||
84 | previous_touch_x = previous_touch_y = -1.0f; | ||
85 | } | ||
86 | } else if (event->type == SDL_EVENT_PEN_AXIS) { | ||
87 | if (event->paxis.axis == SDL_PEN_AXIS_PRESSURE) { | ||
88 | pressure = event->paxis.value; /* remember new pressure for later draws. */ | ||
89 | } else if(event->paxis.axis == SDL_PEN_AXIS_XTILT) { | ||
90 | tilt_x = event->paxis.value; | ||
91 | } else if(event->paxis.axis == SDL_PEN_AXIS_YTILT) { | ||
92 | tilt_y = event->paxis.value; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
97 | } | ||
98 | |||
99 | /* This function runs once per frame, and is the heart of the program. */ | ||
100 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
101 | { | ||
102 | char debug_text[1024]; | ||
103 | |||
104 | /* make sure we're drawing to the window and not the render target */ | ||
105 | SDL_SetRenderTarget(renderer, NULL); | ||
106 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); | ||
107 | SDL_RenderClear(renderer); /* just in case. */ | ||
108 | SDL_RenderTexture(renderer, render_target, NULL, NULL); | ||
109 | SDL_snprintf(debug_text, sizeof(debug_text), "Tilt: %f %f", tilt_x, tilt_y); | ||
110 | SDL_RenderDebugText(renderer, 0, 8, debug_text); | ||
111 | SDL_RenderPresent(renderer); | ||
112 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
113 | } | ||
114 | |||
115 | /* This function runs once at shutdown. */ | ||
116 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
117 | { | ||
118 | SDL_DestroyTexture(render_target); | ||
119 | /* SDL will clean up the window/renderer for us. */ | ||
120 | } | ||
121 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/onmouseover.webp new file mode 100644 index 0000000..f9c4d3d --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/thumbnail.png b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/thumbnail.png new file mode 100644 index 0000000..3403d35 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/pen/01-drawing-lines/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/01-clear/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/README.txt new file mode 100644 index 0000000..ce9ef81 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example code creates an SDL window and renderer, and then clears the | ||
2 | window to a different color every frame, so you'll effectively get a window | ||
3 | that's smoothly fading between colors. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/01-clear/clear.c b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/clear.c new file mode 100644 index 0000000..5b2b7dc --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/clear.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * This example code creates an SDL window and renderer, and then clears the | ||
3 | * window to a different color every frame, so you'll effectively get a window | ||
4 | * that's smoothly fading between colors. | ||
5 | * | ||
6 | * This code is public domain. Feel free to use it for any purpose! | ||
7 | */ | ||
8 | |||
9 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
10 | #include <SDL3/SDL.h> | ||
11 | #include <SDL3/SDL_main.h> | ||
12 | |||
13 | /* We will use this renderer to draw into this window every frame. */ | ||
14 | static SDL_Window *window = NULL; | ||
15 | static SDL_Renderer *renderer = NULL; | ||
16 | |||
17 | /* This function runs once at startup. */ | ||
18 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
19 | { | ||
20 | SDL_SetAppMetadata("Example Renderer Clear", "1.0", "com.example.renderer-clear"); | ||
21 | |||
22 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
23 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
24 | return SDL_APP_FAILURE; | ||
25 | } | ||
26 | |||
27 | if (!SDL_CreateWindowAndRenderer("examples/renderer/clear", 640, 480, 0, &window, &renderer)) { | ||
28 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
29 | return SDL_APP_FAILURE; | ||
30 | } | ||
31 | |||
32 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
33 | } | ||
34 | |||
35 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
36 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
37 | { | ||
38 | if (event->type == SDL_EVENT_QUIT) { | ||
39 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
40 | } | ||
41 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
42 | } | ||
43 | |||
44 | /* This function runs once per frame, and is the heart of the program. */ | ||
45 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
46 | { | ||
47 | const double now = ((double)SDL_GetTicks()) / 1000.0; /* convert from milliseconds to seconds. */ | ||
48 | /* choose the color for the frame we will draw. The sine wave trick makes it fade between colors smoothly. */ | ||
49 | const float red = (float) (0.5 + 0.5 * SDL_sin(now)); | ||
50 | const float green = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 2 / 3)); | ||
51 | const float blue = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 4 / 3)); | ||
52 | SDL_SetRenderDrawColorFloat(renderer, red, green, blue, SDL_ALPHA_OPAQUE_FLOAT); /* new color, full alpha. */ | ||
53 | |||
54 | /* clear the window to the draw color. */ | ||
55 | SDL_RenderClear(renderer); | ||
56 | |||
57 | /* put the newly-cleared rendering on the screen. */ | ||
58 | SDL_RenderPresent(renderer); | ||
59 | |||
60 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
61 | } | ||
62 | |||
63 | /* This function runs once at shutdown. */ | ||
64 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
65 | { | ||
66 | /* SDL will clean up the window/renderer for us. */ | ||
67 | } | ||
68 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/01-clear/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/onmouseover.webp new file mode 100644 index 0000000..a0062fe --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/01-clear/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/thumbnail.png new file mode 100644 index 0000000..b255675 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/01-clear/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/README.txt new file mode 100644 index 0000000..82da8e5 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/README.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | This example creates an SDL window and renderer, and then draws some lines, | ||
2 | rectangles and points to it every frame. | ||
3 | |||
4 | This is just a quick overview of simple drawing primitives; futher examples | ||
5 | will explore them in more detail. | ||
6 | |||
7 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/primitives.c b/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/primitives.c new file mode 100644 index 0000000..5cfd731 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/primitives.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some lines, | ||
3 | * rectangles and points to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_FPoint points[500]; | ||
16 | |||
17 | /* This function runs once at startup. */ | ||
18 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
19 | { | ||
20 | int i; | ||
21 | |||
22 | SDL_SetAppMetadata("Example Renderer Primitives", "1.0", "com.example.renderer-primitives"); | ||
23 | |||
24 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
25 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
26 | return SDL_APP_FAILURE; | ||
27 | } | ||
28 | |||
29 | if (!SDL_CreateWindowAndRenderer("examples/renderer/primitives", 640, 480, 0, &window, &renderer)) { | ||
30 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
31 | return SDL_APP_FAILURE; | ||
32 | } | ||
33 | |||
34 | /* set up some random points */ | ||
35 | for (i = 0; i < SDL_arraysize(points); i++) { | ||
36 | points[i].x = (SDL_randf() * 440.0f) + 100.0f; | ||
37 | points[i].y = (SDL_randf() * 280.0f) + 100.0f; | ||
38 | } | ||
39 | |||
40 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
41 | } | ||
42 | |||
43 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
44 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
45 | { | ||
46 | if (event->type == SDL_EVENT_QUIT) { | ||
47 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
48 | } | ||
49 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
50 | } | ||
51 | |||
52 | /* This function runs once per frame, and is the heart of the program. */ | ||
53 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
54 | { | ||
55 | SDL_FRect rect; | ||
56 | |||
57 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
58 | SDL_SetRenderDrawColor(renderer, 33, 33, 33, SDL_ALPHA_OPAQUE); /* dark gray, full alpha */ | ||
59 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
60 | |||
61 | /* draw a filled rectangle in the middle of the canvas. */ | ||
62 | SDL_SetRenderDrawColor(renderer, 0, 0, 255, SDL_ALPHA_OPAQUE); /* blue, full alpha */ | ||
63 | rect.x = rect.y = 100; | ||
64 | rect.w = 440; | ||
65 | rect.h = 280; | ||
66 | SDL_RenderFillRect(renderer, &rect); | ||
67 | |||
68 | /* draw some points across the canvas. */ | ||
69 | SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE); /* red, full alpha */ | ||
70 | SDL_RenderPoints(renderer, points, SDL_arraysize(points)); | ||
71 | |||
72 | /* draw a unfilled rectangle in-set a little bit. */ | ||
73 | SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); /* green, full alpha */ | ||
74 | rect.x += 30; | ||
75 | rect.y += 30; | ||
76 | rect.w -= 60; | ||
77 | rect.h -= 60; | ||
78 | SDL_RenderRect(renderer, &rect); | ||
79 | |||
80 | /* draw two lines in an X across the whole canvas. */ | ||
81 | SDL_SetRenderDrawColor(renderer, 255, 255, 0, SDL_ALPHA_OPAQUE); /* yellow, full alpha */ | ||
82 | SDL_RenderLine(renderer, 0, 0, 640, 480); | ||
83 | SDL_RenderLine(renderer, 0, 480, 640, 0); | ||
84 | |||
85 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
86 | |||
87 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
88 | } | ||
89 | |||
90 | /* This function runs once at shutdown. */ | ||
91 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
92 | { | ||
93 | /* SDL will clean up the window/renderer for us. */ | ||
94 | } | ||
95 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/thumbnail.png new file mode 100644 index 0000000..4ddf2ab --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/02-primitives/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/03-lines/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/README.txt new file mode 100644 index 0000000..4abeab6 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, and then draws a something | ||
2 | roughly like a Christmas tree with nothing but lines, every frame. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/03-lines/lines.c b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/lines.c new file mode 100644 index 0000000..54f7eb1 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/lines.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some lines | ||
3 | * to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | |||
16 | /* This function runs once at startup. */ | ||
17 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
18 | { | ||
19 | SDL_SetAppMetadata("Example Renderer Lines", "1.0", "com.example.renderer-lines"); | ||
20 | |||
21 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
22 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
23 | return SDL_APP_FAILURE; | ||
24 | } | ||
25 | |||
26 | if (!SDL_CreateWindowAndRenderer("examples/renderer/lines", 640, 480, 0, &window, &renderer)) { | ||
27 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
28 | return SDL_APP_FAILURE; | ||
29 | } | ||
30 | |||
31 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
32 | } | ||
33 | |||
34 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
35 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
36 | { | ||
37 | if (event->type == SDL_EVENT_QUIT) { | ||
38 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
39 | } | ||
40 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
41 | } | ||
42 | |||
43 | /* This function runs once per frame, and is the heart of the program. */ | ||
44 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
45 | { | ||
46 | int i; | ||
47 | |||
48 | /* Lines (line segments, really) are drawn in terms of points: a set of | ||
49 | X and Y coordinates, one set for each end of the line. | ||
50 | (0, 0) is the top left of the window, and larger numbers go down | ||
51 | and to the right. This isn't how geometry works, but this is pretty | ||
52 | standard in 2D graphics. */ | ||
53 | static const SDL_FPoint line_points[] = { | ||
54 | { 100, 354 }, { 220, 230 }, { 140, 230 }, { 320, 100 }, { 500, 230 }, | ||
55 | { 420, 230 }, { 540, 354 }, { 400, 354 }, { 100, 354 } | ||
56 | }; | ||
57 | |||
58 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
59 | SDL_SetRenderDrawColor(renderer, 100, 100, 100, SDL_ALPHA_OPAQUE); /* grey, full alpha */ | ||
60 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
61 | |||
62 | /* You can draw lines, one at a time, like these brown ones... */ | ||
63 | SDL_SetRenderDrawColor(renderer, 127, 49, 32, SDL_ALPHA_OPAQUE); | ||
64 | SDL_RenderLine(renderer, 240, 450, 400, 450); | ||
65 | SDL_RenderLine(renderer, 240, 356, 400, 356); | ||
66 | SDL_RenderLine(renderer, 240, 356, 240, 450); | ||
67 | SDL_RenderLine(renderer, 400, 356, 400, 450); | ||
68 | |||
69 | /* You can also draw a series of connected lines in a single batch... */ | ||
70 | SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); | ||
71 | SDL_RenderLines(renderer, line_points, SDL_arraysize(line_points)); | ||
72 | |||
73 | /* here's a bunch of lines drawn out from a center point in a circle. */ | ||
74 | /* we randomize the color of each line, so it functions as animation. */ | ||
75 | for (i = 0; i < 360; i++) { | ||
76 | const float size = 30.0f; | ||
77 | const float x = 320.0f; | ||
78 | const float y = 95.0f - (size / 2.0f); | ||
79 | SDL_SetRenderDrawColor(renderer, SDL_rand(256), SDL_rand(256), SDL_rand(256), SDL_ALPHA_OPAQUE); | ||
80 | SDL_RenderLine(renderer, x, y, x + SDL_sinf((float) i) * size, y + SDL_cosf((float) i) * size); | ||
81 | } | ||
82 | |||
83 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
84 | |||
85 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
86 | } | ||
87 | |||
88 | /* This function runs once at shutdown. */ | ||
89 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
90 | { | ||
91 | /* SDL will clean up the window/renderer for us. */ | ||
92 | } | ||
93 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/03-lines/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/onmouseover.webp new file mode 100644 index 0000000..5d3b3fc --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/03-lines/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/thumbnail.png new file mode 100644 index 0000000..9d0ff10 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/03-lines/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/04-points/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/04-points/README.txt new file mode 100644 index 0000000..00e9419 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/04-points/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, and then draws a bunch of | ||
2 | single points, moving across the screen. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/04-points/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/04-points/onmouseover.webp new file mode 100644 index 0000000..04582da --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/04-points/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/04-points/points.c b/src/contrib/SDL-3.2.20/examples/renderer/04-points/points.c new file mode 100644 index 0000000..b7b5c21 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/04-points/points.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some points | ||
3 | * to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static Uint64 last_time = 0; | ||
16 | |||
17 | #define WINDOW_WIDTH 640 | ||
18 | #define WINDOW_HEIGHT 480 | ||
19 | |||
20 | #define NUM_POINTS 500 | ||
21 | #define MIN_PIXELS_PER_SECOND 30 /* move at least this many pixels per second. */ | ||
22 | #define MAX_PIXELS_PER_SECOND 60 /* move this many pixels per second at most. */ | ||
23 | |||
24 | /* (track everything as parallel arrays instead of a array of structs, | ||
25 | so we can pass the coordinates to the renderer in a single function call.) */ | ||
26 | |||
27 | /* Points are plotted as a set of X and Y coordinates. | ||
28 | (0, 0) is the top left of the window, and larger numbers go down | ||
29 | and to the right. This isn't how geometry works, but this is pretty | ||
30 | standard in 2D graphics. */ | ||
31 | static SDL_FPoint points[NUM_POINTS]; | ||
32 | static float point_speeds[NUM_POINTS]; | ||
33 | |||
34 | /* This function runs once at startup. */ | ||
35 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
36 | { | ||
37 | int i; | ||
38 | |||
39 | SDL_SetAppMetadata("Example Renderer Points", "1.0", "com.example.renderer-points"); | ||
40 | |||
41 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
42 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
43 | return SDL_APP_FAILURE; | ||
44 | } | ||
45 | |||
46 | if (!SDL_CreateWindowAndRenderer("examples/renderer/points", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
47 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
48 | return SDL_APP_FAILURE; | ||
49 | } | ||
50 | |||
51 | /* set up the data for a bunch of points. */ | ||
52 | for (i = 0; i < SDL_arraysize(points); i++) { | ||
53 | points[i].x = SDL_randf() * ((float) WINDOW_WIDTH); | ||
54 | points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT); | ||
55 | point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND)); | ||
56 | } | ||
57 | |||
58 | last_time = SDL_GetTicks(); | ||
59 | |||
60 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
61 | } | ||
62 | |||
63 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
64 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
65 | { | ||
66 | if (event->type == SDL_EVENT_QUIT) { | ||
67 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
68 | } | ||
69 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
70 | } | ||
71 | |||
72 | /* This function runs once per frame, and is the heart of the program. */ | ||
73 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
74 | { | ||
75 | const Uint64 now = SDL_GetTicks(); | ||
76 | const float elapsed = ((float) (now - last_time)) / 1000.0f; /* seconds since last iteration */ | ||
77 | int i; | ||
78 | |||
79 | /* let's move all our points a little for a new frame. */ | ||
80 | for (i = 0; i < SDL_arraysize(points); i++) { | ||
81 | const float distance = elapsed * point_speeds[i]; | ||
82 | points[i].x += distance; | ||
83 | points[i].y += distance; | ||
84 | if ((points[i].x >= WINDOW_WIDTH) || (points[i].y >= WINDOW_HEIGHT)) { | ||
85 | /* off the screen; restart it elsewhere! */ | ||
86 | if (SDL_rand(2)) { | ||
87 | points[i].x = SDL_randf() * ((float) WINDOW_WIDTH); | ||
88 | points[i].y = 0.0f; | ||
89 | } else { | ||
90 | points[i].x = 0.0f; | ||
91 | points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT); | ||
92 | } | ||
93 | point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND)); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | last_time = now; | ||
98 | |||
99 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
100 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
101 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
102 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */ | ||
103 | SDL_RenderPoints(renderer, points, SDL_arraysize(points)); /* draw all the points! */ | ||
104 | |||
105 | /* You can also draw single points with SDL_RenderPoint(), but it's | ||
106 | cheaper (sometimes significantly so) to do them all at once. */ | ||
107 | |||
108 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
109 | |||
110 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
111 | } | ||
112 | |||
113 | /* This function runs once at shutdown. */ | ||
114 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
115 | { | ||
116 | /* SDL will clean up the window/renderer for us. */ | ||
117 | } | ||
118 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/04-points/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/04-points/thumbnail.png new file mode 100644 index 0000000..5627113 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/04-points/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/README.txt new file mode 100644 index 0000000..26613c7 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, and then draws a few | ||
2 | rectangles that change size each frame. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/onmouseover.webp new file mode 100644 index 0000000..cdfd376 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/rectangles.c b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/rectangles.c new file mode 100644 index 0000000..3aa7242 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/rectangles.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some | ||
3 | * rectangles to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | |||
16 | #define WINDOW_WIDTH 640 | ||
17 | #define WINDOW_HEIGHT 480 | ||
18 | |||
19 | /* This function runs once at startup. */ | ||
20 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
21 | { | ||
22 | SDL_SetAppMetadata("Example Renderer Rectangles", "1.0", "com.example.renderer-rectangles"); | ||
23 | |||
24 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
25 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
26 | return SDL_APP_FAILURE; | ||
27 | } | ||
28 | |||
29 | if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
30 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
31 | return SDL_APP_FAILURE; | ||
32 | } | ||
33 | |||
34 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
35 | } | ||
36 | |||
37 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
38 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
39 | { | ||
40 | if (event->type == SDL_EVENT_QUIT) { | ||
41 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
42 | } | ||
43 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
44 | } | ||
45 | |||
46 | /* This function runs once per frame, and is the heart of the program. */ | ||
47 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
48 | { | ||
49 | SDL_FRect rects[16]; | ||
50 | const Uint64 now = SDL_GetTicks(); | ||
51 | int i; | ||
52 | |||
53 | /* we'll have the rectangles grow and shrink over a few seconds. */ | ||
54 | const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; | ||
55 | const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; | ||
56 | |||
57 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
58 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
59 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
60 | |||
61 | /* Rectangles are comprised of set of X and Y coordinates, plus width and | ||
62 | height. (0, 0) is the top left of the window, and larger numbers go | ||
63 | down and to the right. This isn't how geometry works, but this is | ||
64 | pretty standard in 2D graphics. */ | ||
65 | |||
66 | /* Let's draw a single rectangle (square, really). */ | ||
67 | rects[0].x = rects[0].y = 100; | ||
68 | rects[0].w = rects[0].h = 100 + (100 * scale); | ||
69 | SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE); /* red, full alpha */ | ||
70 | SDL_RenderRect(renderer, &rects[0]); | ||
71 | |||
72 | /* Now let's draw several rectangles with one function call. */ | ||
73 | for (i = 0; i < 3; i++) { | ||
74 | const float size = (i+1) * 50.0f; | ||
75 | rects[i].w = rects[i].h = size + (size * scale); | ||
76 | rects[i].x = (WINDOW_WIDTH - rects[i].w) / 2; /* center it. */ | ||
77 | rects[i].y = (WINDOW_HEIGHT - rects[i].h) / 2; /* center it. */ | ||
78 | } | ||
79 | SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); /* green, full alpha */ | ||
80 | SDL_RenderRects(renderer, rects, 3); /* draw three rectangles at once */ | ||
81 | |||
82 | /* those were rectangle _outlines_, really. You can also draw _filled_ rectangles! */ | ||
83 | rects[0].x = 400; | ||
84 | rects[0].y = 50; | ||
85 | rects[0].w = 100 + (100 * scale); | ||
86 | rects[0].h = 50 + (50 * scale); | ||
87 | SDL_SetRenderDrawColor(renderer, 0, 0, 255, SDL_ALPHA_OPAQUE); /* blue, full alpha */ | ||
88 | SDL_RenderFillRect(renderer, &rects[0]); | ||
89 | |||
90 | /* ...and also fill a bunch of rectangles at once... */ | ||
91 | for (i = 0; i < SDL_arraysize(rects); i++) { | ||
92 | const float w = (float) (WINDOW_WIDTH / SDL_arraysize(rects)); | ||
93 | const float h = i * 8.0f; | ||
94 | rects[i].x = i * w; | ||
95 | rects[i].y = WINDOW_HEIGHT - h; | ||
96 | rects[i].w = w; | ||
97 | rects[i].h = h; | ||
98 | } | ||
99 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */ | ||
100 | SDL_RenderFillRects(renderer, rects, SDL_arraysize(rects)); | ||
101 | |||
102 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
103 | |||
104 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
105 | } | ||
106 | |||
107 | /* This function runs once at shutdown. */ | ||
108 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
109 | { | ||
110 | /* SDL will clean up the window/renderer for us. */ | ||
111 | } | ||
112 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/thumbnail.png new file mode 100644 index 0000000..64e6688 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/05-rectangles/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/06-textures/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/README.txt new file mode 100644 index 0000000..21c3f0b --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, loads a texture from a | ||
2 | .bmp file, and then draws it a few times each frame. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/06-textures/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/onmouseover.webp new file mode 100644 index 0000000..467afd8 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/06-textures/textures.c b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/textures.c new file mode 100644 index 0000000..f4ad707 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/textures.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some | ||
3 | * textures to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_Texture *texture = NULL; | ||
16 | static int texture_width = 0; | ||
17 | static int texture_height = 0; | ||
18 | |||
19 | #define WINDOW_WIDTH 640 | ||
20 | #define WINDOW_HEIGHT 480 | ||
21 | |||
22 | /* This function runs once at startup. */ | ||
23 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
24 | { | ||
25 | SDL_Surface *surface = NULL; | ||
26 | char *bmp_path = NULL; | ||
27 | |||
28 | SDL_SetAppMetadata("Example Renderer Textures", "1.0", "com.example.renderer-textures"); | ||
29 | |||
30 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
31 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
32 | return SDL_APP_FAILURE; | ||
33 | } | ||
34 | |||
35 | if (!SDL_CreateWindowAndRenderer("examples/renderer/textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
36 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
37 | return SDL_APP_FAILURE; | ||
38 | } | ||
39 | |||
40 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
41 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
42 | times) with data from a bitmap file. */ | ||
43 | |||
44 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
45 | Load a .bmp into a surface, move it to a texture from there. */ | ||
46 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
47 | surface = SDL_LoadBMP(bmp_path); | ||
48 | if (!surface) { | ||
49 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
50 | return SDL_APP_FAILURE; | ||
51 | } | ||
52 | |||
53 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
54 | |||
55 | texture_width = surface->w; | ||
56 | texture_height = surface->h; | ||
57 | |||
58 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
59 | if (!texture) { | ||
60 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
61 | return SDL_APP_FAILURE; | ||
62 | } | ||
63 | |||
64 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
70 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
71 | { | ||
72 | if (event->type == SDL_EVENT_QUIT) { | ||
73 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
74 | } | ||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs once per frame, and is the heart of the program. */ | ||
79 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
80 | { | ||
81 | SDL_FRect dst_rect; | ||
82 | const Uint64 now = SDL_GetTicks(); | ||
83 | |||
84 | /* we'll have some textures move around over a few seconds. */ | ||
85 | const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; | ||
86 | const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; | ||
87 | |||
88 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
89 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
90 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
91 | |||
92 | /* Just draw the static texture a few times. You can think of it like a | ||
93 | stamp, there isn't a limit to the number of times you can draw with it. */ | ||
94 | |||
95 | /* top left */ | ||
96 | dst_rect.x = (100.0f * scale); | ||
97 | dst_rect.y = 0.0f; | ||
98 | dst_rect.w = (float) texture_width; | ||
99 | dst_rect.h = (float) texture_height; | ||
100 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
101 | |||
102 | /* center this one. */ | ||
103 | dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f; | ||
104 | dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f; | ||
105 | dst_rect.w = (float) texture_width; | ||
106 | dst_rect.h = (float) texture_height; | ||
107 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
108 | |||
109 | /* bottom right. */ | ||
110 | dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) - (100.0f * scale); | ||
111 | dst_rect.y = (float) (WINDOW_HEIGHT - texture_height); | ||
112 | dst_rect.w = (float) texture_width; | ||
113 | dst_rect.h = (float) texture_height; | ||
114 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
115 | |||
116 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
117 | |||
118 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
119 | } | ||
120 | |||
121 | /* This function runs once at shutdown. */ | ||
122 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
123 | { | ||
124 | SDL_DestroyTexture(texture); | ||
125 | /* SDL will clean up the window/renderer for us. */ | ||
126 | } | ||
127 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/06-textures/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/thumbnail.png new file mode 100644 index 0000000..b33ba31 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/06-textures/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/README.txt new file mode 100644 index 0000000..c250571 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, then a streaming texture that | ||
2 | it will update every frame before drawing it to the screen. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/onmouseover.webp new file mode 100644 index 0000000..7c29693 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/streaming-textures.c b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/streaming-textures.c new file mode 100644 index 0000000..bf309bc --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/streaming-textures.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws a streaming | ||
3 | * texture to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_Texture *texture = NULL; | ||
16 | |||
17 | #define TEXTURE_SIZE 150 | ||
18 | |||
19 | #define WINDOW_WIDTH 640 | ||
20 | #define WINDOW_HEIGHT 480 | ||
21 | |||
22 | /* This function runs once at startup. */ | ||
23 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
24 | { | ||
25 | SDL_SetAppMetadata("Example Renderer Streaming Textures", "1.0", "com.example.renderer-streaming-textures"); | ||
26 | |||
27 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
28 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
29 | return SDL_APP_FAILURE; | ||
30 | } | ||
31 | |||
32 | if (!SDL_CreateWindowAndRenderer("examples/renderer/streaming-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
33 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
34 | return SDL_APP_FAILURE; | ||
35 | } | ||
36 | |||
37 | texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, TEXTURE_SIZE, TEXTURE_SIZE); | ||
38 | if (!texture) { | ||
39 | SDL_Log("Couldn't create streaming texture: %s", SDL_GetError()); | ||
40 | return SDL_APP_FAILURE; | ||
41 | } | ||
42 | |||
43 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
44 | } | ||
45 | |||
46 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
47 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
48 | { | ||
49 | if (event->type == SDL_EVENT_QUIT) { | ||
50 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
51 | } | ||
52 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
53 | } | ||
54 | |||
55 | /* This function runs once per frame, and is the heart of the program. */ | ||
56 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
57 | { | ||
58 | SDL_FRect dst_rect; | ||
59 | const Uint64 now = SDL_GetTicks(); | ||
60 | SDL_Surface *surface = NULL; | ||
61 | |||
62 | /* we'll have some color move around over a few seconds. */ | ||
63 | const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; | ||
64 | const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; | ||
65 | |||
66 | /* To update a streaming texture, you need to lock it first. This gets you access to the pixels. | ||
67 | Note that this is considered a _write-only_ operation: the buffer you get from locking | ||
68 | might not acutally have the existing contents of the texture, and you have to write to every | ||
69 | locked pixel! */ | ||
70 | |||
71 | /* You can use SDL_LockTexture() to get an array of raw pixels, but we're going to use | ||
72 | SDL_LockTextureToSurface() here, because it wraps that array in a temporary SDL_Surface, | ||
73 | letting us use the surface drawing functions instead of lighting up individual pixels. */ | ||
74 | if (SDL_LockTextureToSurface(texture, NULL, &surface)) { | ||
75 | SDL_Rect r; | ||
76 | SDL_FillSurfaceRect(surface, NULL, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 0, 0)); /* make the whole surface black */ | ||
77 | r.w = TEXTURE_SIZE; | ||
78 | r.h = TEXTURE_SIZE / 10; | ||
79 | r.x = 0; | ||
80 | r.y = (int) (((float) (TEXTURE_SIZE - r.h)) * ((scale + 1.0f) / 2.0f)); | ||
81 | SDL_FillSurfaceRect(surface, &r, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 255, 0)); /* make a strip of the surface green */ | ||
82 | SDL_UnlockTexture(texture); /* upload the changes (and frees the temporary surface)! */ | ||
83 | } | ||
84 | |||
85 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
86 | SDL_SetRenderDrawColor(renderer, 66, 66, 66, SDL_ALPHA_OPAQUE); /* grey, full alpha */ | ||
87 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
88 | |||
89 | /* Just draw the static texture a few times. You can think of it like a | ||
90 | stamp, there isn't a limit to the number of times you can draw with it. */ | ||
91 | |||
92 | /* Center this one. It'll draw the latest version of the texture we drew while it was locked. */ | ||
93 | dst_rect.x = ((float) (WINDOW_WIDTH - TEXTURE_SIZE)) / 2.0f; | ||
94 | dst_rect.y = ((float) (WINDOW_HEIGHT - TEXTURE_SIZE)) / 2.0f; | ||
95 | dst_rect.w = dst_rect.h = (float) TEXTURE_SIZE; | ||
96 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
97 | |||
98 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
99 | |||
100 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
101 | } | ||
102 | |||
103 | /* This function runs once at shutdown. */ | ||
104 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
105 | { | ||
106 | SDL_DestroyTexture(texture); | ||
107 | /* SDL will clean up the window/renderer for us. */ | ||
108 | } | ||
109 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/thumbnail.png new file mode 100644 index 0000000..60c2a9f --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/07-streaming-textures/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/README.txt new file mode 100644 index 0000000..4ae46bc --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, loads a texture from a .bmp | ||
2 | file, and then draws it, rotating around the center of the screen. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/onmouseover.webp new file mode 100644 index 0000000..69735ce --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/rotating-textures.c b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/rotating-textures.c new file mode 100644 index 0000000..bf318ef --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/rotating-textures.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some | ||
3 | * rotated textures to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_Texture *texture = NULL; | ||
16 | static int texture_width = 0; | ||
17 | static int texture_height = 0; | ||
18 | |||
19 | #define WINDOW_WIDTH 640 | ||
20 | #define WINDOW_HEIGHT 480 | ||
21 | |||
22 | /* This function runs once at startup. */ | ||
23 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
24 | { | ||
25 | SDL_Surface *surface = NULL; | ||
26 | char *bmp_path = NULL; | ||
27 | |||
28 | SDL_SetAppMetadata("Example Renderer Rotating Textures", "1.0", "com.example.renderer-rotating-textures"); | ||
29 | |||
30 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
31 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
32 | return SDL_APP_FAILURE; | ||
33 | } | ||
34 | |||
35 | if (!SDL_CreateWindowAndRenderer("examples/renderer/rotating-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
36 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
37 | return SDL_APP_FAILURE; | ||
38 | } | ||
39 | |||
40 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
41 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
42 | times) with data from a bitmap file. */ | ||
43 | |||
44 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
45 | Load a .bmp into a surface, move it to a texture from there. */ | ||
46 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
47 | surface = SDL_LoadBMP(bmp_path); | ||
48 | if (!surface) { | ||
49 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
50 | return SDL_APP_FAILURE; | ||
51 | } | ||
52 | |||
53 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
54 | |||
55 | texture_width = surface->w; | ||
56 | texture_height = surface->h; | ||
57 | |||
58 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
59 | if (!texture) { | ||
60 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
61 | return SDL_APP_FAILURE; | ||
62 | } | ||
63 | |||
64 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
70 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
71 | { | ||
72 | if (event->type == SDL_EVENT_QUIT) { | ||
73 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
74 | } | ||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs once per frame, and is the heart of the program. */ | ||
79 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
80 | { | ||
81 | SDL_FPoint center; | ||
82 | SDL_FRect dst_rect; | ||
83 | const Uint64 now = SDL_GetTicks(); | ||
84 | |||
85 | /* we'll have a texture rotate around over 2 seconds (2000 milliseconds). 360 degrees in a circle! */ | ||
86 | const float rotation = (((float) ((int) (now % 2000))) / 2000.0f) * 360.0f; | ||
87 | |||
88 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
89 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
90 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
91 | |||
92 | /* Center this one, and draw it with some rotation so it spins! */ | ||
93 | dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f; | ||
94 | dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f; | ||
95 | dst_rect.w = (float) texture_width; | ||
96 | dst_rect.h = (float) texture_height; | ||
97 | /* rotate it around the center of the texture; you can rotate it from a different point, too! */ | ||
98 | center.x = texture_width / 2.0f; | ||
99 | center.y = texture_height / 2.0f; | ||
100 | SDL_RenderTextureRotated(renderer, texture, NULL, &dst_rect, rotation, ¢er, SDL_FLIP_NONE); | ||
101 | |||
102 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
103 | |||
104 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
105 | } | ||
106 | |||
107 | /* This function runs once at shutdown. */ | ||
108 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
109 | { | ||
110 | SDL_DestroyTexture(texture); | ||
111 | /* SDL will clean up the window/renderer for us. */ | ||
112 | } | ||
113 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/thumbnail.png new file mode 100644 index 0000000..12c51e1 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/08-rotating-textures/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/README.txt new file mode 100644 index 0000000..e13a6ec --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, loads a texture from a .bmp | ||
2 | file, and then draws it, scaling it up and down. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/onmouseover.webp new file mode 100644 index 0000000..bcc967c --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/scaling-textures.c b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/scaling-textures.c new file mode 100644 index 0000000..66060ed --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/scaling-textures.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some | ||
3 | * textures to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_Texture *texture = NULL; | ||
16 | static int texture_width = 0; | ||
17 | static int texture_height = 0; | ||
18 | |||
19 | #define WINDOW_WIDTH 640 | ||
20 | #define WINDOW_HEIGHT 480 | ||
21 | |||
22 | /* This function runs once at startup. */ | ||
23 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
24 | { | ||
25 | SDL_Surface *surface = NULL; | ||
26 | char *bmp_path = NULL; | ||
27 | |||
28 | SDL_SetAppMetadata("Example Renderer Scaling Textures", "1.0", "com.example.renderer-scaling-textures"); | ||
29 | |||
30 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
31 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
32 | return SDL_APP_FAILURE; | ||
33 | } | ||
34 | |||
35 | if (!SDL_CreateWindowAndRenderer("examples/renderer/scaling-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
36 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
37 | return SDL_APP_FAILURE; | ||
38 | } | ||
39 | |||
40 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
41 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
42 | times) with data from a bitmap file. */ | ||
43 | |||
44 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
45 | Load a .bmp into a surface, move it to a texture from there. */ | ||
46 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
47 | surface = SDL_LoadBMP(bmp_path); | ||
48 | if (!surface) { | ||
49 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
50 | return SDL_APP_FAILURE; | ||
51 | } | ||
52 | |||
53 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
54 | |||
55 | texture_width = surface->w; | ||
56 | texture_height = surface->h; | ||
57 | |||
58 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
59 | if (!texture) { | ||
60 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
61 | return SDL_APP_FAILURE; | ||
62 | } | ||
63 | |||
64 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
70 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
71 | { | ||
72 | if (event->type == SDL_EVENT_QUIT) { | ||
73 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
74 | } | ||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs once per frame, and is the heart of the program. */ | ||
79 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
80 | { | ||
81 | SDL_FRect dst_rect; | ||
82 | const Uint64 now = SDL_GetTicks(); | ||
83 | |||
84 | /* we'll have the texture grow and shrink over a few seconds. */ | ||
85 | const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; | ||
86 | const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; | ||
87 | |||
88 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
89 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
90 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
91 | |||
92 | /* center this one and make it grow and shrink. */ | ||
93 | dst_rect.w = (float) texture_width + (texture_width * scale); | ||
94 | dst_rect.h = (float) texture_height + (texture_height * scale); | ||
95 | dst_rect.x = (WINDOW_WIDTH - dst_rect.w) / 2.0f; | ||
96 | dst_rect.y = (WINDOW_HEIGHT - dst_rect.h) / 2.0f; | ||
97 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
98 | |||
99 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
100 | |||
101 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
102 | } | ||
103 | |||
104 | /* This function runs once at shutdown. */ | ||
105 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
106 | { | ||
107 | SDL_DestroyTexture(texture); | ||
108 | /* SDL will clean up the window/renderer for us. */ | ||
109 | } | ||
110 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/thumbnail.png new file mode 100644 index 0000000..c0a24c2 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/09-scaling-textures/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/README.txt new file mode 100644 index 0000000..d76d0cc --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, loads a texture from a .bmp | ||
2 | file, and then draws geometry (arbitrary polygons) using it. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/geometry.c b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/geometry.c new file mode 100644 index 0000000..77ff863 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/geometry.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some | ||
3 | * geometry (arbitrary polygons) to it every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_Texture *texture = NULL; | ||
16 | static int texture_width = 0; | ||
17 | static int texture_height = 0; | ||
18 | |||
19 | #define WINDOW_WIDTH 640 | ||
20 | #define WINDOW_HEIGHT 480 | ||
21 | |||
22 | /* This function runs once at startup. */ | ||
23 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
24 | { | ||
25 | SDL_Surface *surface = NULL; | ||
26 | char *bmp_path = NULL; | ||
27 | |||
28 | SDL_SetAppMetadata("Example Renderer Geometry", "1.0", "com.example.renderer-geometry"); | ||
29 | |||
30 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
31 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
32 | return SDL_APP_FAILURE; | ||
33 | } | ||
34 | |||
35 | if (!SDL_CreateWindowAndRenderer("examples/renderer/geometry", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
36 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
37 | return SDL_APP_FAILURE; | ||
38 | } | ||
39 | |||
40 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
41 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
42 | times) with data from a bitmap file. */ | ||
43 | |||
44 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
45 | Load a .bmp into a surface, move it to a texture from there. */ | ||
46 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
47 | surface = SDL_LoadBMP(bmp_path); | ||
48 | if (!surface) { | ||
49 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
50 | return SDL_APP_FAILURE; | ||
51 | } | ||
52 | |||
53 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
54 | |||
55 | texture_width = surface->w; | ||
56 | texture_height = surface->h; | ||
57 | |||
58 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
59 | if (!texture) { | ||
60 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
61 | return SDL_APP_FAILURE; | ||
62 | } | ||
63 | |||
64 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
70 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
71 | { | ||
72 | if (event->type == SDL_EVENT_QUIT) { | ||
73 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
74 | } | ||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs once per frame, and is the heart of the program. */ | ||
79 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
80 | { | ||
81 | const Uint64 now = SDL_GetTicks(); | ||
82 | |||
83 | /* we'll have the triangle grow and shrink over a few seconds. */ | ||
84 | const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; | ||
85 | const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; | ||
86 | const float size = 200.0f + (200.0f * scale); | ||
87 | |||
88 | SDL_Vertex vertices[4]; | ||
89 | int i; | ||
90 | |||
91 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
92 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
93 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
94 | |||
95 | /* Draw a single triangle with a different color at each vertex. Center this one and make it grow and shrink. */ | ||
96 | /* You always draw triangles with this, but you can string triangles together to form polygons. */ | ||
97 | SDL_zeroa(vertices); | ||
98 | vertices[0].position.x = ((float) WINDOW_WIDTH) / 2.0f; | ||
99 | vertices[0].position.y = (((float) WINDOW_HEIGHT) - size) / 2.0f; | ||
100 | vertices[0].color.r = 1.0f; | ||
101 | vertices[0].color.a = 1.0f; | ||
102 | vertices[1].position.x = (((float) WINDOW_WIDTH) + size) / 2.0f; | ||
103 | vertices[1].position.y = (((float) WINDOW_HEIGHT) + size) / 2.0f; | ||
104 | vertices[1].color.g = 1.0f; | ||
105 | vertices[1].color.a = 1.0f; | ||
106 | vertices[2].position.x = (((float) WINDOW_WIDTH) - size) / 2.0f; | ||
107 | vertices[2].position.y = (((float) WINDOW_HEIGHT) + size) / 2.0f; | ||
108 | vertices[2].color.b = 1.0f; | ||
109 | vertices[2].color.a = 1.0f; | ||
110 | |||
111 | SDL_RenderGeometry(renderer, NULL, vertices, 3, NULL, 0); | ||
112 | |||
113 | /* you can also map a texture to the geometry! Texture coordinates go from 0.0f to 1.0f. That will be the location | ||
114 | in the texture bound to this vertex. */ | ||
115 | SDL_zeroa(vertices); | ||
116 | vertices[0].position.x = 10.0f; | ||
117 | vertices[0].position.y = 10.0f; | ||
118 | vertices[0].color.r = vertices[0].color.g = vertices[0].color.b = vertices[0].color.a = 1.0f; | ||
119 | vertices[0].tex_coord.x = 0.0f; | ||
120 | vertices[0].tex_coord.y = 0.0f; | ||
121 | vertices[1].position.x = 150.0f; | ||
122 | vertices[1].position.y = 10.0f; | ||
123 | vertices[1].color.r = vertices[1].color.g = vertices[1].color.b = vertices[1].color.a = 1.0f; | ||
124 | vertices[1].tex_coord.x = 1.0f; | ||
125 | vertices[1].tex_coord.y = 0.0f; | ||
126 | vertices[2].position.x = 10.0f; | ||
127 | vertices[2].position.y = 150.0f; | ||
128 | vertices[2].color.r = vertices[2].color.g = vertices[2].color.b = vertices[2].color.a = 1.0f; | ||
129 | vertices[2].tex_coord.x = 0.0f; | ||
130 | vertices[2].tex_coord.y = 1.0f; | ||
131 | SDL_RenderGeometry(renderer, texture, vertices, 3, NULL, 0); | ||
132 | |||
133 | /* Did that only draw half of the texture? You can do multiple triangles sharing some vertices, | ||
134 | using indices, to get the whole thing on the screen: */ | ||
135 | |||
136 | /* Let's just move this over so it doesn't overlap... */ | ||
137 | for (i = 0; i < 3; i++) { | ||
138 | vertices[i].position.x += 450; | ||
139 | } | ||
140 | |||
141 | /* we need one more vertex, since the two triangles can share two of them. */ | ||
142 | vertices[3].position.x = 600.0f; | ||
143 | vertices[3].position.y = 150.0f; | ||
144 | vertices[3].color.r = vertices[3].color.g = vertices[3].color.b = vertices[3].color.a = 1.0f; | ||
145 | vertices[3].tex_coord.x = 1.0f; | ||
146 | vertices[3].tex_coord.y = 1.0f; | ||
147 | |||
148 | /* And an index to tell it to reuse some of the vertices between triangles... */ | ||
149 | { | ||
150 | /* 4 vertices, but 6 actual places they used. Indices need less bandwidth to transfer and can reorder vertices easily! */ | ||
151 | const int indices[] = { 0, 1, 2, 1, 2, 3 }; | ||
152 | SDL_RenderGeometry(renderer, texture, vertices, 4, indices, SDL_arraysize(indices)); | ||
153 | } | ||
154 | |||
155 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
156 | |||
157 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
158 | } | ||
159 | |||
160 | /* This function runs once at shutdown. */ | ||
161 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
162 | { | ||
163 | SDL_DestroyTexture(texture); | ||
164 | /* SDL will clean up the window/renderer for us. */ | ||
165 | } | ||
166 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/onmouseover.webp new file mode 100644 index 0000000..37a518c --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/thumbnail.png new file mode 100644 index 0000000..89195fb --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/10-geometry/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/README.txt new file mode 100644 index 0000000..66f233b --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/README.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | This example creates an SDL window and renderer, loads a texture from a | ||
2 | .bmp file, and then draws it a few times each frame, adjusting the colors. | ||
3 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/color-mods.c b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/color-mods.c new file mode 100644 index 0000000..8877232 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/color-mods.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some | ||
3 | * textures to it every frame, adjusting their color. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_Texture *texture = NULL; | ||
16 | static int texture_width = 0; | ||
17 | static int texture_height = 0; | ||
18 | |||
19 | #define WINDOW_WIDTH 640 | ||
20 | #define WINDOW_HEIGHT 480 | ||
21 | |||
22 | /* This function runs once at startup. */ | ||
23 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
24 | { | ||
25 | SDL_Surface *surface = NULL; | ||
26 | char *bmp_path = NULL; | ||
27 | |||
28 | SDL_SetAppMetadata("Example Renderer Color Mods", "1.0", "com.example.renderer-color-mods"); | ||
29 | |||
30 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
31 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
32 | return SDL_APP_FAILURE; | ||
33 | } | ||
34 | |||
35 | if (!SDL_CreateWindowAndRenderer("examples/renderer/color-mods", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
36 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
37 | return SDL_APP_FAILURE; | ||
38 | } | ||
39 | |||
40 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
41 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
42 | times) with data from a bitmap file. */ | ||
43 | |||
44 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
45 | Load a .bmp into a surface, move it to a texture from there. */ | ||
46 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
47 | surface = SDL_LoadBMP(bmp_path); | ||
48 | if (!surface) { | ||
49 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
50 | return SDL_APP_FAILURE; | ||
51 | } | ||
52 | |||
53 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
54 | |||
55 | texture_width = surface->w; | ||
56 | texture_height = surface->h; | ||
57 | |||
58 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
59 | if (!texture) { | ||
60 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
61 | return SDL_APP_FAILURE; | ||
62 | } | ||
63 | |||
64 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
70 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
71 | { | ||
72 | if (event->type == SDL_EVENT_QUIT) { | ||
73 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
74 | } | ||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs once per frame, and is the heart of the program. */ | ||
79 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
80 | { | ||
81 | SDL_FRect dst_rect; | ||
82 | const double now = ((double)SDL_GetTicks()) / 1000.0; /* convert from milliseconds to seconds. */ | ||
83 | /* choose the modulation values for the center texture. The sine wave trick makes it fade between colors smoothly. */ | ||
84 | const float red = (float) (0.5 + 0.5 * SDL_sin(now)); | ||
85 | const float green = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 2 / 3)); | ||
86 | const float blue = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 4 / 3)); | ||
87 | |||
88 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
89 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
90 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
91 | |||
92 | /* Just draw the static texture a few times. You can think of it like a | ||
93 | stamp, there isn't a limit to the number of times you can draw with it. */ | ||
94 | |||
95 | /* Color modulation multiplies each pixel's red, green, and blue intensities by the mod values, | ||
96 | so multiplying by 1.0f will leave a color intensity alone, 0.0f will shut off that color | ||
97 | completely, etc. */ | ||
98 | |||
99 | /* top left; let's make this one blue! */ | ||
100 | dst_rect.x = 0.0f; | ||
101 | dst_rect.y = 0.0f; | ||
102 | dst_rect.w = (float) texture_width; | ||
103 | dst_rect.h = (float) texture_height; | ||
104 | SDL_SetTextureColorModFloat(texture, 0.0f, 0.0f, 1.0f); /* kill all red and green. */ | ||
105 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
106 | |||
107 | /* center this one, and have it cycle through red/green/blue modulations. */ | ||
108 | dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f; | ||
109 | dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f; | ||
110 | dst_rect.w = (float) texture_width; | ||
111 | dst_rect.h = (float) texture_height; | ||
112 | SDL_SetTextureColorModFloat(texture, red, green, blue); | ||
113 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
114 | |||
115 | /* bottom right; let's make this one red! */ | ||
116 | dst_rect.x = (float) (WINDOW_WIDTH - texture_width); | ||
117 | dst_rect.y = (float) (WINDOW_HEIGHT - texture_height); | ||
118 | dst_rect.w = (float) texture_width; | ||
119 | dst_rect.h = (float) texture_height; | ||
120 | SDL_SetTextureColorModFloat(texture, 1.0f, 0.0f, 0.0f); /* kill all green and blue. */ | ||
121 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
122 | |||
123 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
124 | |||
125 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
126 | } | ||
127 | |||
128 | /* This function runs once at shutdown. */ | ||
129 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
130 | { | ||
131 | SDL_DestroyTexture(texture); | ||
132 | /* SDL will clean up the window/renderer for us. */ | ||
133 | } | ||
134 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/onmouseover.webp new file mode 100644 index 0000000..2157063 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/thumbnail.png new file mode 100644 index 0000000..d471112 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/11-color-mods/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/README.txt new file mode 100644 index 0000000..9da7c7a --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/README.txt | |||
@@ -0,0 +1,4 @@ | |||
1 | This example creates an SDL window and renderer, loads a texture | ||
2 | from a .bmp file, and then draws it a few times each frame, adjusting | ||
3 | the viewport before each draw. | ||
4 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/thumbnail.png new file mode 100644 index 0000000..bad5521 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/viewport.c b/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/viewport.c new file mode 100644 index 0000000..0a6c015 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/14-viewport/viewport.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some | ||
3 | * textures to it every frame, adjusting the viewport. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | static SDL_Texture *texture = NULL; | ||
16 | static int texture_width = 0; | ||
17 | static int texture_height = 0; | ||
18 | |||
19 | #define WINDOW_WIDTH 640 | ||
20 | #define WINDOW_HEIGHT 480 | ||
21 | |||
22 | /* This function runs once at startup. */ | ||
23 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
24 | { | ||
25 | SDL_Surface *surface = NULL; | ||
26 | char *bmp_path = NULL; | ||
27 | |||
28 | SDL_SetAppMetadata("Example Renderer Viewport", "1.0", "com.example.renderer-viewport"); | ||
29 | |||
30 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
31 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
32 | return SDL_APP_FAILURE; | ||
33 | } | ||
34 | |||
35 | if (!SDL_CreateWindowAndRenderer("examples/renderer/viewport", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
36 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
37 | return SDL_APP_FAILURE; | ||
38 | } | ||
39 | |||
40 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
41 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
42 | times) with data from a bitmap file. */ | ||
43 | |||
44 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
45 | Load a .bmp into a surface, move it to a texture from there. */ | ||
46 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
47 | surface = SDL_LoadBMP(bmp_path); | ||
48 | if (!surface) { | ||
49 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
50 | return SDL_APP_FAILURE; | ||
51 | } | ||
52 | |||
53 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
54 | |||
55 | texture_width = surface->w; | ||
56 | texture_height = surface->h; | ||
57 | |||
58 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
59 | if (!texture) { | ||
60 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
61 | return SDL_APP_FAILURE; | ||
62 | } | ||
63 | |||
64 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
65 | |||
66 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
67 | } | ||
68 | |||
69 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
70 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
71 | { | ||
72 | if (event->type == SDL_EVENT_QUIT) { | ||
73 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
74 | } | ||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs once per frame, and is the heart of the program. */ | ||
79 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
80 | { | ||
81 | SDL_FRect dst_rect = { 0, 0, (float) texture_width, (float) texture_height }; | ||
82 | SDL_Rect viewport; | ||
83 | |||
84 | /* Setting a viewport has the effect of limiting the area that rendering | ||
85 | can happen, and making coordinate (0, 0) live somewhere else in the | ||
86 | window. It does _not_ scale rendering to fit the viewport. */ | ||
87 | |||
88 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
89 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
90 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
91 | |||
92 | /* Draw once with the whole window as the viewport. */ | ||
93 | viewport.x = 0; | ||
94 | viewport.y = 0; | ||
95 | viewport.w = WINDOW_WIDTH / 2; | ||
96 | viewport.h = WINDOW_HEIGHT / 2; | ||
97 | SDL_SetRenderViewport(renderer, NULL); /* NULL means "use the whole window" */ | ||
98 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
99 | |||
100 | /* top right quarter of the window. */ | ||
101 | viewport.x = WINDOW_WIDTH / 2; | ||
102 | viewport.y = WINDOW_HEIGHT / 2; | ||
103 | viewport.w = WINDOW_WIDTH / 2; | ||
104 | viewport.h = WINDOW_HEIGHT / 2; | ||
105 | SDL_SetRenderViewport(renderer, &viewport); | ||
106 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
107 | |||
108 | /* bottom 20% of the window. Note it clips the width! */ | ||
109 | viewport.x = 0; | ||
110 | viewport.y = WINDOW_HEIGHT - (WINDOW_HEIGHT / 5); | ||
111 | viewport.w = WINDOW_WIDTH / 5; | ||
112 | viewport.h = WINDOW_HEIGHT / 5; | ||
113 | SDL_SetRenderViewport(renderer, &viewport); | ||
114 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
115 | |||
116 | /* what happens if you try to draw above the viewport? It should clip! */ | ||
117 | viewport.x = 100; | ||
118 | viewport.y = 200; | ||
119 | viewport.w = WINDOW_WIDTH; | ||
120 | viewport.h = WINDOW_HEIGHT; | ||
121 | SDL_SetRenderViewport(renderer, &viewport); | ||
122 | dst_rect.y = -50; | ||
123 | SDL_RenderTexture(renderer, texture, NULL, &dst_rect); | ||
124 | |||
125 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
126 | |||
127 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
128 | } | ||
129 | |||
130 | /* This function runs once at shutdown. */ | ||
131 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
132 | { | ||
133 | SDL_DestroyTexture(texture); | ||
134 | /* SDL will clean up the window/renderer for us. */ | ||
135 | } | ||
136 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/README.txt new file mode 100644 index 0000000..48c9f1f --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/README.txt | |||
@@ -0,0 +1,5 @@ | |||
1 | This example creates an SDL window and renderer, loads a texture | ||
2 | from a .bmp file, and stretches it across the window. Each frame, we move | ||
3 | the clipping rectangle around, so only a small square of the texture is | ||
4 | actually drawn. | ||
5 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/cliprect.c b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/cliprect.c new file mode 100644 index 0000000..058072c --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/cliprect.c | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws a scene | ||
3 | * to it every frame, while sliding around a clipping rectangle. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | #define WINDOW_WIDTH 640 | ||
13 | #define WINDOW_HEIGHT 480 | ||
14 | #define CLIPRECT_SIZE 250 | ||
15 | #define CLIPRECT_SPEED 200 /* pixels per second */ | ||
16 | |||
17 | /* We will use this renderer to draw into this window every frame. */ | ||
18 | static SDL_Window *window = NULL; | ||
19 | static SDL_Renderer *renderer = NULL; | ||
20 | static SDL_Texture *texture = NULL; | ||
21 | static SDL_FPoint cliprect_position; | ||
22 | static SDL_FPoint cliprect_direction; | ||
23 | static Uint64 last_time = 0; | ||
24 | |||
25 | /* A lot of this program is examples/renderer/02-primitives, so we have a good | ||
26 | visual that we can slide a clip rect around. The actual new magic in here | ||
27 | is the SDL_SetRenderClipRect() function. */ | ||
28 | |||
29 | /* This function runs once at startup. */ | ||
30 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
31 | { | ||
32 | SDL_Surface *surface = NULL; | ||
33 | char *bmp_path = NULL; | ||
34 | |||
35 | SDL_SetAppMetadata("Example Renderer Clipping Rectangle", "1.0", "com.example.renderer-cliprect"); | ||
36 | |||
37 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
38 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
39 | return SDL_APP_FAILURE; | ||
40 | } | ||
41 | |||
42 | if (!SDL_CreateWindowAndRenderer("examples/renderer/cliprect", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
43 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
44 | return SDL_APP_FAILURE; | ||
45 | } | ||
46 | |||
47 | cliprect_direction.x = cliprect_direction.y = 1.0f; | ||
48 | |||
49 | last_time = SDL_GetTicks(); | ||
50 | |||
51 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
52 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
53 | times) with data from a bitmap file. */ | ||
54 | |||
55 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
56 | Load a .bmp into a surface, move it to a texture from there. */ | ||
57 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
58 | surface = SDL_LoadBMP(bmp_path); | ||
59 | if (!surface) { | ||
60 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
61 | return SDL_APP_FAILURE; | ||
62 | } | ||
63 | |||
64 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
65 | |||
66 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
67 | if (!texture) { | ||
68 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
69 | return SDL_APP_FAILURE; | ||
70 | } | ||
71 | |||
72 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
73 | |||
74 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
75 | } | ||
76 | |||
77 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
78 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
79 | { | ||
80 | if (event->type == SDL_EVENT_QUIT) { | ||
81 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
82 | } | ||
83 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
84 | } | ||
85 | |||
86 | /* This function runs once per frame, and is the heart of the program. */ | ||
87 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
88 | { | ||
89 | const SDL_Rect cliprect = { (int) SDL_roundf(cliprect_position.x), (int) SDL_roundf(cliprect_position.y), CLIPRECT_SIZE, CLIPRECT_SIZE }; | ||
90 | const Uint64 now = SDL_GetTicks(); | ||
91 | const float elapsed = ((float) (now - last_time)) / 1000.0f; /* seconds since last iteration */ | ||
92 | const float distance = elapsed * CLIPRECT_SPEED; | ||
93 | |||
94 | /* Set a new clipping rectangle position */ | ||
95 | cliprect_position.x += distance * cliprect_direction.x; | ||
96 | if (cliprect_position.x < 0.0f) { | ||
97 | cliprect_position.x = 0.0f; | ||
98 | cliprect_direction.x = 1.0f; | ||
99 | } else if (cliprect_position.x >= (WINDOW_WIDTH - CLIPRECT_SIZE)) { | ||
100 | cliprect_position.x = (WINDOW_WIDTH - CLIPRECT_SIZE) - 1; | ||
101 | cliprect_direction.x = -1.0f; | ||
102 | } | ||
103 | |||
104 | cliprect_position.y += distance * cliprect_direction.y; | ||
105 | if (cliprect_position.y < 0.0f) { | ||
106 | cliprect_position.y = 0.0f; | ||
107 | cliprect_direction.y = 1.0f; | ||
108 | } else if (cliprect_position.y >= (WINDOW_HEIGHT - CLIPRECT_SIZE)) { | ||
109 | cliprect_position.y = (WINDOW_HEIGHT - CLIPRECT_SIZE) - 1; | ||
110 | cliprect_direction.y = -1.0f; | ||
111 | } | ||
112 | SDL_SetRenderClipRect(renderer, &cliprect); | ||
113 | |||
114 | last_time = now; | ||
115 | |||
116 | /* okay, now draw! */ | ||
117 | |||
118 | /* Note that SDL_RenderClear is _not_ affected by the clipping rectangle! */ | ||
119 | SDL_SetRenderDrawColor(renderer, 33, 33, 33, SDL_ALPHA_OPAQUE); /* grey, full alpha */ | ||
120 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
121 | |||
122 | /* stretch the texture across the entire window. Only the piece in the | ||
123 | clipping rectangle will actually render, though! */ | ||
124 | SDL_RenderTexture(renderer, texture, NULL, NULL); | ||
125 | |||
126 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
127 | |||
128 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
129 | } | ||
130 | |||
131 | /* This function runs once at shutdown. */ | ||
132 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
133 | { | ||
134 | SDL_DestroyTexture(texture); | ||
135 | /* SDL will clean up the window/renderer for us. */ | ||
136 | } | ||
137 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/onmouseover.webp new file mode 100644 index 0000000..943eeef --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/thumbnail.png new file mode 100644 index 0000000..127e6fa --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/15-cliprect/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/README.txt new file mode 100644 index 0000000..dd474e6 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/README.txt | |||
@@ -0,0 +1,12 @@ | |||
1 | This example creates an SDL window and renderer, and draws a | ||
2 | rotating texture to it, reads back the rendered pixels, converts them to | ||
3 | black and white, and then draws the converted image to a corner of the | ||
4 | screen. | ||
5 | |||
6 | This isn't necessarily an efficient thing to do--in real life one might | ||
7 | want to do this sort of thing with a render target--but it's just a visual | ||
8 | example of how to use SDL_RenderReadPixels(). | ||
9 | |||
10 | A better, but less visual, use of SDL_RenderReadPixels() is to make | ||
11 | screenshots: you grab the current contents of the screen, and save the pixels | ||
12 | as a bitmap file or whatever. | ||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/onmouseover.webp b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/onmouseover.webp new file mode 100644 index 0000000..bb4e5c4 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/onmouseover.webp | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/read-pixels.c b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/read-pixels.c new file mode 100644 index 0000000..556b490 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/read-pixels.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and draws a | ||
3 | * rotating texture to it, reads back the rendered pixels, converts them to | ||
4 | * black and white, and then draws the converted image to a corner of the | ||
5 | * screen. | ||
6 | * | ||
7 | * This isn't necessarily an efficient thing to do--in real life one might | ||
8 | * want to do this sort of thing with a render target--but it's just a visual | ||
9 | * example of how to use SDL_RenderReadPixels(). | ||
10 | * | ||
11 | * This code is public domain. Feel free to use it for any purpose! | ||
12 | */ | ||
13 | |||
14 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
15 | #include <SDL3/SDL.h> | ||
16 | #include <SDL3/SDL_main.h> | ||
17 | |||
18 | /* We will use this renderer to draw into this window every frame. */ | ||
19 | static SDL_Window *window = NULL; | ||
20 | static SDL_Renderer *renderer = NULL; | ||
21 | static SDL_Texture *texture = NULL; | ||
22 | static int texture_width = 0; | ||
23 | static int texture_height = 0; | ||
24 | static SDL_Texture *converted_texture = NULL; | ||
25 | static int converted_texture_width = 0; | ||
26 | static int converted_texture_height = 0; | ||
27 | |||
28 | #define WINDOW_WIDTH 640 | ||
29 | #define WINDOW_HEIGHT 480 | ||
30 | |||
31 | /* This function runs once at startup. */ | ||
32 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
33 | { | ||
34 | SDL_Surface *surface = NULL; | ||
35 | char *bmp_path = NULL; | ||
36 | |||
37 | SDL_SetAppMetadata("Example Renderer Read Pixels", "1.0", "com.example.renderer-read-pixels"); | ||
38 | |||
39 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
40 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
41 | return SDL_APP_FAILURE; | ||
42 | } | ||
43 | |||
44 | if (!SDL_CreateWindowAndRenderer("examples/renderer/read-pixels", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
45 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
46 | return SDL_APP_FAILURE; | ||
47 | } | ||
48 | |||
49 | /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D | ||
50 | engines refer to these as "sprites." We'll do a static texture (upload once, draw many | ||
51 | times) with data from a bitmap file. */ | ||
52 | |||
53 | /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. | ||
54 | Load a .bmp into a surface, move it to a texture from there. */ | ||
55 | SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ | ||
56 | surface = SDL_LoadBMP(bmp_path); | ||
57 | if (!surface) { | ||
58 | SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); | ||
59 | return SDL_APP_FAILURE; | ||
60 | } | ||
61 | |||
62 | SDL_free(bmp_path); /* done with this, the file is loaded. */ | ||
63 | |||
64 | texture_width = surface->w; | ||
65 | texture_height = surface->h; | ||
66 | |||
67 | texture = SDL_CreateTextureFromSurface(renderer, surface); | ||
68 | if (!texture) { | ||
69 | SDL_Log("Couldn't create static texture: %s", SDL_GetError()); | ||
70 | return SDL_APP_FAILURE; | ||
71 | } | ||
72 | |||
73 | SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ | ||
74 | |||
75 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
76 | } | ||
77 | |||
78 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
79 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
80 | { | ||
81 | if (event->type == SDL_EVENT_QUIT) { | ||
82 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
83 | } | ||
84 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
85 | } | ||
86 | |||
87 | /* This function runs once per frame, and is the heart of the program. */ | ||
88 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
89 | { | ||
90 | const Uint64 now = SDL_GetTicks(); | ||
91 | SDL_Surface *surface; | ||
92 | SDL_FPoint center; | ||
93 | SDL_FRect dst_rect; | ||
94 | |||
95 | /* we'll have a texture rotate around over 2 seconds (2000 milliseconds). 360 degrees in a circle! */ | ||
96 | const float rotation = (((float) ((int) (now % 2000))) / 2000.0f) * 360.0f; | ||
97 | |||
98 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
99 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
100 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
101 | |||
102 | /* Center this one, and draw it with some rotation so it spins! */ | ||
103 | dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f; | ||
104 | dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f; | ||
105 | dst_rect.w = (float) texture_width; | ||
106 | dst_rect.h = (float) texture_height; | ||
107 | /* rotate it around the center of the texture; you can rotate it from a different point, too! */ | ||
108 | center.x = texture_width / 2.0f; | ||
109 | center.y = texture_height / 2.0f; | ||
110 | SDL_RenderTextureRotated(renderer, texture, NULL, &dst_rect, rotation, ¢er, SDL_FLIP_NONE); | ||
111 | |||
112 | /* this next whole thing is _super_ expensive. Seriously, don't do this in real life. */ | ||
113 | |||
114 | /* Download the pixels of what has just been rendered. This has to wait for the GPU to finish rendering it and everything before it, | ||
115 | and then make an expensive copy from the GPU to system RAM! */ | ||
116 | surface = SDL_RenderReadPixels(renderer, NULL); | ||
117 | |||
118 | /* This is also expensive, but easier: convert the pixels to a format we want. */ | ||
119 | if (surface && (surface->format != SDL_PIXELFORMAT_RGBA8888) && (surface->format != SDL_PIXELFORMAT_BGRA8888)) { | ||
120 | SDL_Surface *converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA8888); | ||
121 | SDL_DestroySurface(surface); | ||
122 | surface = converted; | ||
123 | } | ||
124 | |||
125 | if (surface) { | ||
126 | /* Rebuild converted_texture if the dimensions have changed (window resized, etc). */ | ||
127 | if ((surface->w != converted_texture_width) || (surface->h != converted_texture_height)) { | ||
128 | SDL_DestroyTexture(converted_texture); | ||
129 | converted_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, surface->w, surface->h); | ||
130 | if (!converted_texture) { | ||
131 | SDL_Log("Couldn't (re)create conversion texture: %s", SDL_GetError()); | ||
132 | return SDL_APP_FAILURE; | ||
133 | } | ||
134 | converted_texture_width = surface->w; | ||
135 | converted_texture_height = surface->h; | ||
136 | } | ||
137 | |||
138 | /* Turn each pixel into either black or white. This is a lousy technique but it works here. | ||
139 | In real life, something like Floyd-Steinberg dithering might work | ||
140 | better: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering*/ | ||
141 | int x, y; | ||
142 | for (y = 0; y < surface->h; y++) { | ||
143 | Uint32 *pixels = (Uint32 *) (((Uint8 *) surface->pixels) + (y * surface->pitch)); | ||
144 | for (x = 0; x < surface->w; x++) { | ||
145 | Uint8 *p = (Uint8 *) (&pixels[x]); | ||
146 | const Uint32 average = (((Uint32) p[1]) + ((Uint32) p[2]) + ((Uint32) p[3])) / 3; | ||
147 | if (average == 0) { | ||
148 | p[0] = p[3] = 0xFF; p[1] = p[2] = 0; /* make pure black pixels red. */ | ||
149 | } else { | ||
150 | p[1] = p[2] = p[3] = (average > 50) ? 0xFF : 0x00; /* make everything else either black or white. */ | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* upload the processed pixels back into a texture. */ | ||
156 | SDL_UpdateTexture(converted_texture, NULL, surface->pixels, surface->pitch); | ||
157 | SDL_DestroySurface(surface); | ||
158 | |||
159 | /* draw the texture to the top-left of the screen. */ | ||
160 | dst_rect.x = dst_rect.y = 0.0f; | ||
161 | dst_rect.w = ((float) WINDOW_WIDTH) / 4.0f; | ||
162 | dst_rect.h = ((float) WINDOW_HEIGHT) / 4.0f; | ||
163 | SDL_RenderTexture(renderer, converted_texture, NULL, &dst_rect); | ||
164 | } | ||
165 | |||
166 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
167 | |||
168 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
169 | } | ||
170 | |||
171 | /* This function runs once at shutdown. */ | ||
172 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
173 | { | ||
174 | SDL_DestroyTexture(converted_texture); | ||
175 | SDL_DestroyTexture(texture); | ||
176 | /* SDL will clean up the window/renderer for us. */ | ||
177 | } | ||
178 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/thumbnail.png new file mode 100644 index 0000000..8da02ac --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/17-read-pixels/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/README.txt b/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/README.txt new file mode 100644 index 0000000..0f0c868 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/README.txt | |||
@@ -0,0 +1,4 @@ | |||
1 | This example creates an SDL window and renderer, and draws some text | ||
2 | using SDL_RenderDebugText(). This is not quality text rendering, but it can | ||
3 | be helpful for simple apps, debugging, or showing something in a pinch. | ||
4 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/debug-text.c b/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/debug-text.c new file mode 100644 index 0000000..62005e6 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/debug-text.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * This example creates an SDL window and renderer, and then draws some text | ||
3 | * using SDL_RenderDebugText() every frame. | ||
4 | * | ||
5 | * This code is public domain. Feel free to use it for any purpose! | ||
6 | */ | ||
7 | |||
8 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
9 | #include <SDL3/SDL.h> | ||
10 | #include <SDL3/SDL_main.h> | ||
11 | |||
12 | /* We will use this renderer to draw into this window every frame. */ | ||
13 | static SDL_Window *window = NULL; | ||
14 | static SDL_Renderer *renderer = NULL; | ||
15 | |||
16 | #define WINDOW_WIDTH 640 | ||
17 | #define WINDOW_HEIGHT 480 | ||
18 | |||
19 | /* This function runs once at startup. */ | ||
20 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
21 | { | ||
22 | SDL_SetAppMetadata("Example Renderer Debug Texture", "1.0", "com.example.renderer-debug-text"); | ||
23 | |||
24 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
25 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
26 | return SDL_APP_FAILURE; | ||
27 | } | ||
28 | |||
29 | if (!SDL_CreateWindowAndRenderer("examples/renderer/debug-text", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { | ||
30 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
31 | return SDL_APP_FAILURE; | ||
32 | } | ||
33 | |||
34 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
35 | } | ||
36 | |||
37 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
38 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
39 | { | ||
40 | if (event->type == SDL_EVENT_QUIT) { | ||
41 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
42 | } | ||
43 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
44 | } | ||
45 | |||
46 | /* This function runs once per frame, and is the heart of the program. */ | ||
47 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
48 | { | ||
49 | const int charsize = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE; | ||
50 | |||
51 | /* as you can see from this, rendering draws over whatever was drawn before it. */ | ||
52 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ | ||
53 | SDL_RenderClear(renderer); /* start with a blank canvas. */ | ||
54 | |||
55 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */ | ||
56 | SDL_RenderDebugText(renderer, 272, 100, "Hello world!"); | ||
57 | SDL_RenderDebugText(renderer, 224, 150, "This is some debug text."); | ||
58 | |||
59 | SDL_SetRenderDrawColor(renderer, 51, 102, 255, SDL_ALPHA_OPAQUE); /* light blue, full alpha */ | ||
60 | SDL_RenderDebugText(renderer, 184, 200, "You can do it in different colors."); | ||
61 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */ | ||
62 | |||
63 | SDL_SetRenderScale(renderer, 4.0f, 4.0f); | ||
64 | SDL_RenderDebugText(renderer, 14, 65, "It can be scaled."); | ||
65 | SDL_SetRenderScale(renderer, 1.0f, 1.0f); | ||
66 | SDL_RenderDebugText(renderer, 64, 350, "This only does ASCII chars. So this laughing emoji won't draw: 🤣"); | ||
67 | |||
68 | SDL_RenderDebugTextFormat(renderer, (float) ((WINDOW_WIDTH - (charsize * 46)) / 2), 400, "(This program has been running for %" SDL_PRIu64 " seconds.)", SDL_GetTicks() / 1000); | ||
69 | |||
70 | SDL_RenderPresent(renderer); /* put it all on the screen! */ | ||
71 | |||
72 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
73 | } | ||
74 | |||
75 | /* This function runs once at shutdown. */ | ||
76 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
77 | { | ||
78 | /* SDL will clean up the window/renderer for us. */ | ||
79 | } | ||
80 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/thumbnail.png b/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/thumbnail.png new file mode 100644 index 0000000..f08e469 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/renderer/18-debug-text/thumbnail.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/template-category.html b/src/contrib/SDL-3.2.20/examples/template-category.html new file mode 100644 index 0000000..909b2c6 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/template-category.html | |||
@@ -0,0 +1,41 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html lang="en-us"> | ||
3 | <head> | ||
4 | <meta charset="utf-8" /> | ||
5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||
6 | <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
7 | <title>@project_name@ Examples: @category_description@</title> | ||
8 | <link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" /> | ||
9 | <link | ||
10 | rel="stylesheet" | ||
11 | type="text/css" | ||
12 | href="/@project_name@/examples.css" | ||
13 | /> | ||
14 | <style> | ||
15 | main > h1 { | ||
16 | margin-top: 0; | ||
17 | } | ||
18 | </style> | ||
19 | |||
20 | <meta property="og:type" content="website"> | ||
21 | <meta property="og:title" content="@project_name@ Examples: @category_description@"> | ||
22 | <meta property="og:description" content="@project_name@ Examples: @category_description@"> | ||
23 | <meta property="og:image" content="@preview_image@" /> | ||
24 | |||
25 | </head> | ||
26 | <body> | ||
27 | <header> | ||
28 | <a href="/">@project_name@ Examples</a> | ||
29 | </header> | ||
30 | <main> | ||
31 | <nav class="breadcrumb"> | ||
32 | <ul> | ||
33 | <li><a href="/@project_name@/">@project_name@</a></li> | ||
34 | <li><a href="/@project_name@/@category_name@">@category_name@</a></li> | ||
35 | </ul> | ||
36 | </nav> | ||
37 | <h1>@project_name@ examples: @category_description@</h1> | ||
38 | <div class="list">@examples_list_html@</div> | ||
39 | </main> | ||
40 | </body> | ||
41 | </html> | ||
diff --git a/src/contrib/SDL-3.2.20/examples/template-homepage.html b/src/contrib/SDL-3.2.20/examples/template-homepage.html new file mode 100644 index 0000000..46951b2 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/template-homepage.html | |||
@@ -0,0 +1,41 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html lang="en-us"> | ||
3 | <head> | ||
4 | <meta charset="utf-8" /> | ||
5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||
6 | <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
7 | <title>@project_name@ Examples</title> | ||
8 | <link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" /> | ||
9 | <link | ||
10 | rel="stylesheet" | ||
11 | type="text/css" | ||
12 | href="/@project_name@/examples.css" | ||
13 | /> | ||
14 | <style> | ||
15 | main > h1 { | ||
16 | margin-top: 0; | ||
17 | } | ||
18 | </style> | ||
19 | |||
20 | <meta property="og:type" content="website"> | ||
21 | <meta property="og:title" content="@project_name@ Examples"> | ||
22 | <meta property="og:description" content="@project_name@ Examples"> | ||
23 | <meta property="og:image" content="@preview_image@" /> | ||
24 | |||
25 | </head> | ||
26 | <body> | ||
27 | <header> | ||
28 | <a href="/">SDL Examples</a> | ||
29 | </header> | ||
30 | <main> | ||
31 | <nav class="breadcrumb"> | ||
32 | <ul> | ||
33 | <li><a href="/@project_name@">@project_name@</a></li> | ||
34 | </ul> | ||
35 | </nav> | ||
36 | <h1>@project_name@ examples</h1> | ||
37 | |||
38 | @homepage_list_html@ | ||
39 | </main> | ||
40 | </body> | ||
41 | </html> | ||
diff --git a/src/contrib/SDL-3.2.20/examples/template-placeholder.png b/src/contrib/SDL-3.2.20/examples/template-placeholder.png new file mode 100644 index 0000000..202df95 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/template-placeholder.png | |||
Binary files differ | |||
diff --git a/src/contrib/SDL-3.2.20/examples/template.c b/src/contrib/SDL-3.2.20/examples/template.c new file mode 100644 index 0000000..6719cc9 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/template.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * This example code $WHAT_IT_DOES. | ||
3 | * | ||
4 | * This code is public domain. Feel free to use it for any purpose! | ||
5 | */ | ||
6 | |||
7 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
8 | #include <SDL3/SDL.h> | ||
9 | #include <SDL3/SDL_main.h> | ||
10 | |||
11 | /* We will use this renderer to draw into this window every frame. */ | ||
12 | static SDL_Window *window = NULL; | ||
13 | static SDL_Renderer *renderer = NULL; | ||
14 | |||
15 | |||
16 | /* This function runs once at startup. */ | ||
17 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
18 | { | ||
19 | SDL_SetAppMetadata("Example HUMAN READABLE NAME", "1.0", "com.example.CATEGORY-NAME"); | ||
20 | |||
21 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
22 | SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); | ||
23 | return SDL_APP_FAILURE; | ||
24 | } | ||
25 | |||
26 | if (!SDL_CreateWindowAndRenderer("examples/CATEGORY/NAME", 640, 480, 0, &window, &renderer)) { | ||
27 | SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); | ||
28 | return SDL_APP_FAILURE; | ||
29 | } | ||
30 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
31 | } | ||
32 | |||
33 | /* This function runs when a new event (mouse input, keypresses, etc) occurs. */ | ||
34 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
35 | { | ||
36 | if (event->type == SDL_EVENT_QUIT) { | ||
37 | return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ | ||
38 | } | ||
39 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
40 | } | ||
41 | |||
42 | /* This function runs once per frame, and is the heart of the program. */ | ||
43 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
44 | { | ||
45 | return SDL_APP_CONTINUE; /* carry on with the program! */ | ||
46 | } | ||
47 | |||
48 | /* This function runs once at shutdown. */ | ||
49 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
50 | { | ||
51 | /* SDL will clean up the window/renderer for us. */ | ||
52 | } | ||
53 | |||
diff --git a/src/contrib/SDL-3.2.20/examples/template.css b/src/contrib/SDL-3.2.20/examples/template.css new file mode 100644 index 0000000..8e86723 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/template.css | |||
@@ -0,0 +1,284 @@ | |||
1 | /** from ghwikipp.css */ | ||
2 | :root { | ||
3 | color-scheme: dark light; /* both supported */ | ||
4 | } | ||
5 | |||
6 | body { | ||
7 | background-color: white; | ||
8 | padding: 2vw; | ||
9 | color: #333; | ||
10 | max-width: 1200px; | ||
11 | margin: 0 auto; | ||
12 | font-size: 16px; | ||
13 | line-height: 1.5; | ||
14 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", | ||
15 | Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; | ||
16 | overflow-wrap: break-word; | ||
17 | } | ||
18 | |||
19 | a { | ||
20 | color: #0969da; | ||
21 | /* text-decoration: none; */ | ||
22 | } | ||
23 | |||
24 | a:visited { | ||
25 | color: #064998; | ||
26 | } | ||
27 | |||
28 | h1 { | ||
29 | border-bottom: 2px solid #efefef; | ||
30 | } | ||
31 | |||
32 | h2 { | ||
33 | border-bottom: 1px solid #efefef; | ||
34 | } | ||
35 | |||
36 | p { | ||
37 | max-width: 85ch; | ||
38 | } | ||
39 | |||
40 | li { | ||
41 | max-width: 85ch; | ||
42 | } | ||
43 | |||
44 | div.sourceCode { | ||
45 | background-color: #f6f8fa; | ||
46 | max-width: 100%; | ||
47 | padding: 16px; | ||
48 | } | ||
49 | |||
50 | code { | ||
51 | background-color: #f6f8fa; | ||
52 | padding: 0px; | ||
53 | font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, | ||
54 | "Liberation Mono", monospace; | ||
55 | } | ||
56 | |||
57 | table { | ||
58 | border: 1px solid #808080; | ||
59 | border-collapse: collapse; | ||
60 | } | ||
61 | |||
62 | td { | ||
63 | border: 1px solid #808080; | ||
64 | padding: 5px; | ||
65 | } | ||
66 | |||
67 | tr:nth-child(even) { | ||
68 | background-color: #f6f8fa; | ||
69 | } | ||
70 | |||
71 | .wikitopbanner { | ||
72 | background-color: #efefef; | ||
73 | padding: 10px; | ||
74 | margin-bottom: 10px; | ||
75 | width: auto; | ||
76 | } | ||
77 | |||
78 | .wikibottombanner { | ||
79 | background-color: #efefef; | ||
80 | padding: 10px; | ||
81 | margin-top: 10px; | ||
82 | width: auto; | ||
83 | } | ||
84 | |||
85 | .alertBox { | ||
86 | background-color: #f8d7da; | ||
87 | border: 1px solid #f5c6cb; | ||
88 | max-width: 60%; | ||
89 | padding: 10; | ||
90 | margin: auto; | ||
91 | } | ||
92 | |||
93 | .anchorImage { | ||
94 | visibility: hidden; | ||
95 | padding-left: 0.2em; | ||
96 | color: #fff; | ||
97 | } | ||
98 | |||
99 | .anchorText:hover .anchorImage { | ||
100 | visibility: visible; | ||
101 | } | ||
102 | |||
103 | hr { | ||
104 | display: block; | ||
105 | height: 1px; | ||
106 | border: 0; | ||
107 | border-top: 1px solid #efefef; | ||
108 | margin: 1em 0; | ||
109 | padding: 0; | ||
110 | } | ||
111 | |||
112 | /* Text and background color for dark mode */ | ||
113 | @media (prefers-color-scheme: dark) { | ||
114 | body { | ||
115 | color: #e6edf3; | ||
116 | background-color: #0d1117; | ||
117 | } | ||
118 | |||
119 | h1 { | ||
120 | border-color: rgba(48, 54, 61, 0.7); | ||
121 | } | ||
122 | |||
123 | h2 { | ||
124 | border-color: rgba(48, 54, 61, 0.7); | ||
125 | } | ||
126 | |||
127 | hr { | ||
128 | border-color: rgba(48, 54, 61, 0.7); | ||
129 | } | ||
130 | |||
131 | div.sourceCode { | ||
132 | background-color: #161b22; | ||
133 | } | ||
134 | |||
135 | code { | ||
136 | background-color: #161b22; | ||
137 | } | ||
138 | |||
139 | a { | ||
140 | color: #4493f8; | ||
141 | } | ||
142 | |||
143 | a:visited { | ||
144 | color: #2f66ad; | ||
145 | } | ||
146 | |||
147 | table { | ||
148 | border-color: rgba(48, 54, 61, 0.7); | ||
149 | } | ||
150 | |||
151 | td { | ||
152 | border-color: rgba(48, 54, 61, 0.7); | ||
153 | } | ||
154 | |||
155 | tr:nth-child(even) { | ||
156 | background-color: #161b22; | ||
157 | } | ||
158 | |||
159 | .wikitopbanner { | ||
160 | background-color: #263040; | ||
161 | } | ||
162 | |||
163 | .wikibottombanner { | ||
164 | background-color: #263040; | ||
165 | } | ||
166 | |||
167 | .anchorText:hover .anchorImage { | ||
168 | filter: invert(100%); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | @media print { | ||
173 | body { | ||
174 | font-size: 12px; | ||
175 | } | ||
176 | |||
177 | table { | ||
178 | font-size: inherit; | ||
179 | } | ||
180 | |||
181 | a:visited { | ||
182 | color: #0969da; | ||
183 | } | ||
184 | |||
185 | .wikitopbanner, | ||
186 | .anchorText, | ||
187 | .wikibottombanner { | ||
188 | display: none; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | /** additional (& overrides) for examples */ | ||
193 | header { | ||
194 | background-color: #efefef; | ||
195 | padding: 10px; | ||
196 | font-size: 2rem; | ||
197 | } | ||
198 | |||
199 | header > a, | ||
200 | header > a:hover, | ||
201 | header > a:visited { | ||
202 | color: inherit; | ||
203 | text-decoration: none; | ||
204 | } | ||
205 | |||
206 | .breadcrumb { | ||
207 | padding: 0.75rem 0.75rem; | ||
208 | } | ||
209 | |||
210 | .breadcrumb ul { | ||
211 | display: flex; | ||
212 | flex-wrap: wrap; | ||
213 | list-style: none; | ||
214 | margin: 0; | ||
215 | padding: 0; | ||
216 | } | ||
217 | |||
218 | .breadcrumb li:not(:last-child)::after { | ||
219 | display: inline-block; | ||
220 | margin: 0 0.25rem; | ||
221 | content: "»"; | ||
222 | } | ||
223 | |||
224 | .list { | ||
225 | display: flex; | ||
226 | flex-flow: row wrap; | ||
227 | gap: 24px; | ||
228 | } | ||
229 | |||
230 | .list > a > div { | ||
231 | width: 200px; | ||
232 | border: 5px solid #efefef; | ||
233 | border-radius: 5px; | ||
234 | background: #efefef; | ||
235 | |||
236 | display: flex; | ||
237 | flex-flow: column nowrap; | ||
238 | |||
239 | transition: border 0.25s; | ||
240 | } | ||
241 | |||
242 | .list > a > div:hover { | ||
243 | border-color: #064998; | ||
244 | } | ||
245 | |||
246 | .list > a > div > img { | ||
247 | width: 100%; | ||
248 | border-radius: 5px; | ||
249 | } | ||
250 | |||
251 | .list > a > div > div { | ||
252 | text-align: center; | ||
253 | } | ||
254 | |||
255 | .list > a, | ||
256 | .list > a:visited { | ||
257 | display: block; | ||
258 | color: inherit; | ||
259 | text-decoration: none; | ||
260 | } | ||
261 | .list > a:hover { | ||
262 | color: #0969da; | ||
263 | } | ||
264 | |||
265 | @media (prefers-color-scheme: dark) { | ||
266 | header { | ||
267 | background-color: #263040; | ||
268 | } | ||
269 | |||
270 | .breadcrumb li:not(:last-child)::after { | ||
271 | color: #efefef; | ||
272 | } | ||
273 | |||
274 | .list > a > div { | ||
275 | border-color: #333; | ||
276 | background: #333; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | @media only screen and (max-width: 992px) { | ||
281 | .list > a > div { | ||
282 | width: 150px; | ||
283 | } | ||
284 | } | ||
diff --git a/src/contrib/SDL-3.2.20/examples/template.html b/src/contrib/SDL-3.2.20/examples/template.html new file mode 100644 index 0000000..3e43946 --- /dev/null +++ b/src/contrib/SDL-3.2.20/examples/template.html | |||
@@ -0,0 +1,292 @@ | |||
1 | <!doctype html> | ||
2 | <html lang="en-us"> | ||
3 | <head> | ||
4 | <meta charset="utf-8"> | ||
5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
6 | <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
7 | <title>@project_name@ Example: @category_name@/@example_name@</title> | ||
8 | <link rel="icon" href="/@project_name@/thumbnail.png" type="image/png" /> | ||
9 | |||
10 | <meta property="og:type" content="website"> | ||
11 | <meta property="og:title" content="@project_name@ Example: @category_name@/@example_name@"> | ||
12 | <meta property="og:description" content="@description@"> | ||
13 | <meta property="og:image" content="@preview_image@" /> | ||
14 | |||
15 | <link rel="stylesheet" type="text/css" href="/@project_name@/examples.css" /> | ||
16 | <style> | ||
17 | main { | ||
18 | display: flex; | ||
19 | } | ||
20 | |||
21 | main > #sidebar { | ||
22 | flex: 0 1 25%; | ||
23 | border-left: 2px solid #efefef; | ||
24 | padding: 1rem 1rem; | ||
25 | } | ||
26 | |||
27 | main > #content { | ||
28 | flex: 1 1 auto; | ||
29 | margin-bottom: 16px; | ||
30 | } | ||
31 | |||
32 | main > #content > h1 { | ||
33 | margin-top: 0; | ||
34 | } | ||
35 | |||
36 | main > #sidebar ul { | ||
37 | list-style-type: none; | ||
38 | padding: 0; | ||
39 | margin: 0; | ||
40 | } | ||
41 | |||
42 | main > #sidebar li { | ||
43 | padding: 2px 0; | ||
44 | } | ||
45 | |||
46 | #example-description { | ||
47 | max-width: 85ch; | ||
48 | margin-bottom: 16px; | ||
49 | } | ||
50 | |||
51 | .canvas-container { | ||
52 | display: flex; | ||
53 | align-items: center; | ||
54 | justify-content: center; | ||
55 | } | ||
56 | |||
57 | #canvas { | ||
58 | max-width: 100%; | ||
59 | box-shadow: 0 0 0.5rem #7787; | ||
60 | } | ||
61 | |||
62 | #output-container { | ||
63 | position: fixed; | ||
64 | top: 100%; | ||
65 | left: 0; | ||
66 | right: 0; | ||
67 | bottom: 0; | ||
68 | |||
69 | background-color: black; | ||
70 | border: none; | ||
71 | border-top: 1px solid #778; | ||
72 | margin: 0; | ||
73 | padding: 1rem; | ||
74 | |||
75 | transition: top 0.25s; | ||
76 | } | ||
77 | |||
78 | #output-container::before { | ||
79 | position: absolute; | ||
80 | bottom: 100%; | ||
81 | right: 1rem; | ||
82 | |||
83 | content: 'Console'; | ||
84 | font-size: 1.5rem; | ||
85 | color: white; | ||
86 | background: black; | ||
87 | border: 1px solid #778; | ||
88 | border-bottom: none; | ||
89 | padding: 0.75rem 1.5rem; | ||
90 | border-radius: 0.5rem 0.5rem 0 0; | ||
91 | } | ||
92 | |||
93 | #output-container:hover, | ||
94 | #output-container:focus-within { | ||
95 | top: 50%; | ||
96 | } | ||
97 | |||
98 | #output-container:focus-within { | ||
99 | border-top: 2px solid orange; | ||
100 | } | ||
101 | |||
102 | #output-container:focus-within::before { | ||
103 | border: 2px solid orange; | ||
104 | border-bottom: none; | ||
105 | } | ||
106 | |||
107 | #output { | ||
108 | width: 100%; | ||
109 | height: 100%; | ||
110 | padding: 0; | ||
111 | margin: 0; | ||
112 | |||
113 | border: none; | ||
114 | background: black; | ||
115 | color: white; | ||
116 | outline: none; | ||
117 | resize: none; | ||
118 | |||
119 | font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, | ||
120 | "Liberation Mono", monospace; | ||
121 | } | ||
122 | |||
123 | #source-code { | ||
124 | position: fixed; | ||
125 | top: 100%; | ||
126 | left: 0; | ||
127 | right: 0; | ||
128 | bottom: 0; | ||
129 | |||
130 | background: #e0eaee; | ||
131 | padding: 1rem; | ||
132 | |||
133 | transition: top 0.25s; | ||
134 | } | ||
135 | |||
136 | #source-code::before { | ||
137 | position: absolute; | ||
138 | bottom: 100%; | ||
139 | left: 1rem; | ||
140 | |||
141 | content: 'Source code'; | ||
142 | font-size: 1.5rem; | ||
143 | background: linear-gradient(to bottom, #789, #e0eaee); | ||
144 | padding: 0.75rem 1.5rem; | ||
145 | border-radius: 0.5rem 0.5rem 0 0; | ||
146 | |||
147 | /* Used for a hack to avoid tab labels showing on top of tabs; see | ||
148 | comment below for details. */ | ||
149 | transition: bottom 0.25s; | ||
150 | } | ||
151 | |||
152 | #source-code:hover, | ||
153 | #source-code:focus-within { | ||
154 | top: 50%; | ||
155 | } | ||
156 | |||
157 | #source-code:focus-within { | ||
158 | border-top: 2px solid orange; | ||
159 | } | ||
160 | |||
161 | #source-code:focus-within::before { | ||
162 | border: 2px solid orange; | ||
163 | border-bottom: none; | ||
164 | } | ||
165 | |||
166 | #source-code-contents { | ||
167 | height: 100%; | ||
168 | overflow: scroll; | ||
169 | } | ||
170 | |||
171 | /* Hack: Sinze z-index only goes one way, and both tab labels should be | ||
172 | behind each other's tab, put the former on top (higher z-index) and | ||
173 | make the latter one disappear when the former is hovered. */ | ||
174 | #output-container:hover ~ #source-code::before, | ||
175 | #output-container:focus-within ~ #source-code::before { | ||
176 | bottom: -100%; | ||
177 | } | ||
178 | |||
179 | @media (prefers-color-scheme: dark) { | ||
180 | main > #sidebar { | ||
181 | border-color: rgba(48, 54, 61, 0.7); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | @media only screen and (max-width: 992px) { | ||
186 | main { | ||
187 | flex-direction: column; | ||
188 | } | ||
189 | |||
190 | main > #sidebar { | ||
191 | border: none; | ||
192 | } | ||
193 | } | ||
194 | </style> | ||
195 | <link rel="stylesheet" type="text/css" href="highlight.css"> | ||
196 | </head> | ||
197 | <body> | ||
198 | <header> | ||
199 | <a href="/">SDL Examples</a> | ||
200 | </header> | ||
201 | <main> | ||
202 | <div id="content"> | ||
203 | <nav class="breadcrumb"> | ||
204 | <ul> | ||
205 | <li><a href="/@project_name@">@project_name@</a></li> | ||
206 | <li><a href="/@project_name@/@category_name@">@category_name@</a></li> | ||
207 | <li><a href="/@project_name@/@category_name@/@example_name@">@example_name@</a></li> | ||
208 | </ul> | ||
209 | </nav> | ||
210 | <hr/> | ||
211 | <div id="example-description">@description@</div> | ||
212 | <div class="canvas-container"> | ||
213 | <canvas | ||
214 | id="canvas" | ||
215 | oncontextmenu="event.preventDefault()" | ||
216 | tabindex="-1" | ||
217 | ></canvas> | ||
218 | </div> | ||
219 | </div> | ||
220 | <div id="sidebar"> | ||
221 | <h3>Other examples:</h3> | ||
222 | @other_examples_html@ | ||
223 | </div> | ||
224 | </main> | ||
225 | |||
226 | <div id="output-container"> | ||
227 | <textarea id="output" rows="8" spellcheck="false" readonly></textarea> | ||
228 | </div> | ||
229 | |||
230 | <div id="source-code" tabindex="1"> | ||
231 | <div id="source-code-contents">@htmlified_source_code@</div> | ||
232 | </div> | ||
233 | |||
234 | <script type='text/javascript'> | ||
235 | var Module = { | ||
236 | preRun: [], | ||
237 | postRun: [], | ||
238 | print: (function() { | ||
239 | var element = document.getElementById('output'); | ||
240 | if (element) element.value = ''; // clear browser cache | ||
241 | return function(text) { | ||
242 | var elem = document.getElementById('output-container'); | ||
243 | if (elem.style['top'] == '') { | ||
244 | elem.style['top'] = '50%'; | ||
245 | setTimeout(function() { elem.style['top'] = ''; }, 3000); | ||
246 | } | ||
247 | |||
248 | if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); | ||
249 | // These replacements are necessary if you render to raw HTML | ||
250 | //text = text.replace(/&/g, "&"); | ||
251 | //text = text.replace(/</g, "<"); | ||
252 | //text = text.replace(/>/g, ">"); | ||
253 | //text = text.replace('\n', '<br>', 'g'); | ||
254 | console.log(text); | ||
255 | if (element) { | ||
256 | element.value += text + "\n"; | ||
257 | element.scrollTop = element.scrollHeight; // focus on bottom | ||
258 | } | ||
259 | }; | ||
260 | })(), | ||
261 | printErr: function(text) { Module.print(text) }, | ||
262 | canvas: (() => { | ||
263 | var canvas = document.getElementById('canvas'); | ||
264 | |||
265 | // As a default initial behavior, pop up an alert when webgl context is lost. To make your | ||
266 | // application robust, you may want to override this behavior before shipping! | ||
267 | // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2 | ||
268 | canvas.addEventListener("webglcontextlost", (e) => { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false); | ||
269 | |||
270 | return canvas; | ||
271 | })(), | ||
272 | setStatus: (text) => {}, | ||
273 | totalDependencies: 0, | ||
274 | monitorRunDependencies: (left) => { | ||
275 | this.totalDependencies = Math.max(this.totalDependencies, left); | ||
276 | Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.'); | ||
277 | } | ||
278 | }; | ||
279 | Module.setStatus('Downloading...'); | ||
280 | window.onerror = (event) => { | ||
281 | // TODO: do not warn on ok events like simulating an infinite loop or exitStatus | ||
282 | Module.setStatus('Exception thrown, see JavaScript console'); | ||
283 | Module.setStatus = (text) => { | ||
284 | if (text) console.error('[post-exception status] ' + text); | ||
285 | }; | ||
286 | }; | ||
287 | </script> | ||
288 | <script async type="text/javascript" src="@javascript_file@"></script> | ||
289 | </body> | ||
290 | </html> | ||
291 | |||
292 | |||