Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc6ad6f718 | ||
|
|
9bd5e7db33 | ||
|
|
5cc8e349a5 | ||
|
|
0046d526b0 | ||
|
|
fc9947b87f | ||
|
|
35aaa6c519 | ||
|
|
3195746189 | ||
|
|
d1d5679d14 | ||
|
|
ebb161f1f5 | ||
|
|
68be8e55ec | ||
|
|
5ed963b53d | ||
|
|
5e5ff835a9 | ||
|
|
f5d251c33b | ||
|
|
d186f66c2c | ||
|
|
da361a1452 | ||
|
|
a43ae21014 | ||
|
|
6749780356 | ||
|
|
1c49248b72 | ||
|
|
63a03ae632 | ||
|
|
a8bff31a7c | ||
|
|
793e87a203 | ||
|
|
642e0653b2 | ||
|
|
d26abcb9d5 | ||
|
|
a358d8ddbd | ||
|
|
f7c4d62234 | ||
|
|
06a49e09ba | ||
|
|
629baaaec3 | ||
|
|
932d195eb0 | ||
|
|
3e31a88f78 | ||
|
|
cba46642c6 | ||
|
|
8c84892250 | ||
|
|
d14da0e61f | ||
|
|
8bdc994b75 | ||
|
|
6a70d6de9f | ||
|
|
2523661c8f | ||
|
|
fa27308897 | ||
|
|
e58eb10d6d | ||
|
|
a29ea641ab | ||
|
|
28ff425c89 | ||
|
|
e8418f89e0 | ||
|
|
9ca09484a6 | ||
|
|
9291ef6572 | ||
|
|
6f8ab74d6b | ||
|
|
881e0ea1f6 | ||
|
|
6a6a1a52c7 | ||
|
|
62f4b857ef | ||
|
|
3b378e2b29 | ||
|
|
041447eaa4 | ||
|
|
a6b2b02930 | ||
|
|
b7811180ba | ||
|
|
2cbf1bb6e0 | ||
|
|
8890fa9e1f | ||
|
|
23f7cb03a6 | ||
|
|
486a440668 | ||
|
|
a717411edd | ||
|
|
5e862ceadc | ||
|
|
78e164fce4 | ||
|
|
c13b11c501 | ||
|
|
8921b9fd0c | ||
|
|
1d9fea28fe | ||
|
|
d0d5cb0e66 | ||
|
|
e25ccd02fd | ||
|
|
3635cebf25 | ||
|
|
cfbcdc236b | ||
|
|
7871d3930e | ||
|
|
932b457725 | ||
|
|
e9f99a0542 | ||
|
|
0d58da536c | ||
|
|
583acb9053 | ||
|
|
babb111b6f | ||
|
|
866e133aa9 | ||
|
|
170521aba6 | ||
|
|
c8882a3f6e | ||
|
|
5fce52e0ad | ||
|
|
0b708f1515 | ||
|
|
6e99fd0a8b | ||
|
|
1243b457be | ||
|
|
c910a16834 | ||
|
|
0ec1a2548a | ||
|
|
4ea8ab7b6d | ||
|
|
05465b791e | ||
|
|
9949096fba | ||
|
|
ea5762265e | ||
|
|
78732042cb | ||
|
|
f10671d9c0 | ||
|
|
7d5a4cee8e | ||
|
|
d560623e00 | ||
|
|
3f88dfaaee | ||
|
|
e1bd75e00d | ||
|
|
e32cff9dac | ||
|
|
243ced7498 | ||
|
|
fceeb11cdd | ||
|
|
233fcb8226 | ||
|
|
8bc45ccedc | ||
|
|
f7ab6a641a | ||
|
|
8eaa91f309 | ||
|
|
23fdf6e1bd | ||
|
|
1431f27cfa | ||
|
|
29cb4c2211 | ||
|
|
3f09858203 | ||
|
|
b6d6ee471c | ||
|
|
25ce524470 | ||
|
|
921e10bbb3 | ||
|
|
36fc496226 | ||
|
|
0618452224 | ||
|
|
ca64115bfe | ||
|
|
1fc3ab8e31 | ||
|
|
9233bd8d75 | ||
|
|
e7a024bcdb | ||
|
|
158968e2c2 | ||
|
|
dadbee9bad | ||
|
|
5710568af8 | ||
|
|
165499b9d4 | ||
|
|
093d9b49b5 | ||
|
|
7956a1382a | ||
|
|
0db2195404 | ||
|
|
2e3816783f | ||
|
|
3985e66b94 | ||
|
|
f248ae316a | ||
|
|
4536deee47 | ||
|
|
f9e09d968d | ||
|
|
1ba17f5225 | ||
|
|
3442b9b481 | ||
|
|
8746ee9ec9 | ||
|
|
ef7fbf4027 | ||
|
|
964c32dd0d | ||
|
|
970fe2b4db | ||
|
|
f816e75cc0 | ||
|
|
2e8df45b38 | ||
|
|
643e5442c3 | ||
|
|
82ccf65ce1 | ||
|
|
1ae6912be5 | ||
|
|
c003e6665e | ||
|
|
a254fdd669 | ||
|
|
c0362abf67 | ||
|
|
d13313503c | ||
|
|
2a78c78e77 | ||
|
|
10e16d7905 | ||
|
|
ecb4625465 | ||
|
|
b4e36944d7 | ||
|
|
9b09ccb765 | ||
|
|
94213f9fd6 | ||
|
|
f591aa82fd | ||
|
|
2ef5968e0d | ||
|
|
ca03a1307e | ||
|
|
fe916d263f | ||
|
|
de7233a012 | ||
|
|
d26ecec04f | ||
|
|
fddea0c449 | ||
|
|
2c1c1a442b | ||
|
|
d1948afe4b | ||
|
|
ac06b05332 | ||
|
|
7d11dde0b1 | ||
|
|
73add013dd | ||
|
|
4e2ba827e3 | ||
|
|
9ac0c0cb74 | ||
|
|
11a909b58d | ||
|
|
17cf6e0636 | ||
|
|
7d0aca506a | ||
|
|
7cd7b4dc4f | ||
|
|
6d4f606eeb | ||
|
|
1ccd444aad | ||
|
|
3bfca35f3a | ||
|
|
3e5217066f | ||
|
|
4da50571eb | ||
|
|
d4593d0686 | ||
|
|
a53cf4b797 | ||
|
|
bcbf990a5f | ||
|
|
45514ae2f4 | ||
|
|
0847e9c544 | ||
|
|
27cf2f032d |
No files matched your search
@@ -1,4 +1,5 @@
|
|||||||
build/
|
build/
|
||||||
|
dist/
|
||||||
*.o
|
*.o
|
||||||
*.obj
|
*.obj
|
||||||
*.a
|
*.a
|
||||||
@@ -7,8 +8,8 @@ build/
|
|||||||
*.dylib
|
*.dylib
|
||||||
*.dll
|
*.dll
|
||||||
*.exe
|
*.exe
|
||||||
aee_2026
|
aee_arcade
|
||||||
_aee_2026
|
_aee_arcade
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
.cache/
|
.cache/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(aee_2026 VERSION 0.1.0 LANGUAGES CXX)
|
project(aee_arcade VERSION 0.1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||||
@@ -50,7 +50,9 @@ set(ENTITY_SOURCES_BASE
|
|||||||
source/game/entities/concrete/rolling_rock.cpp
|
source/game/entities/concrete/rolling_rock.cpp
|
||||||
source/game/entities/concrete/wall_trap.cpp
|
source/game/entities/concrete/wall_trap.cpp
|
||||||
source/game/entities/concrete/floor_trap.cpp
|
source/game/entities/concrete/floor_trap.cpp
|
||||||
|
source/game/entities/concrete/hole.cpp
|
||||||
source/game/entities/concrete/dust.cpp
|
source/game/entities/concrete/dust.cpp
|
||||||
|
source/game/entities/concrete/solid_props.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Entitats que criden directament símbols de Player (com WhipAttack via
|
# Entitats que criden directament símbols de Player (com WhipAttack via
|
||||||
@@ -79,6 +81,7 @@ set(APP_SOURCES
|
|||||||
source/core/input/mouse.cpp
|
source/core/input/mouse.cpp
|
||||||
source/core/rendering/screen.cpp
|
source/core/rendering/screen.cpp
|
||||||
source/core/rendering/canvas.cpp
|
source/core/rendering/canvas.cpp
|
||||||
|
source/core/rendering/lighting.cpp
|
||||||
source/core/rendering/notifier.cpp
|
source/core/rendering/notifier.cpp
|
||||||
source/core/rendering/render_info.cpp
|
source/core/rendering/render_info.cpp
|
||||||
source/core/rendering/gif.cpp
|
source/core/rendering/gif.cpp
|
||||||
@@ -91,6 +94,11 @@ set(APP_SOURCES
|
|||||||
source/core/rendering/sprite/moving_sprite.cpp
|
source/core/rendering/sprite/moving_sprite.cpp
|
||||||
source/core/rendering/sprite/animated_sprite.cpp
|
source/core/rendering/sprite/animated_sprite.cpp
|
||||||
source/core/rendering/sprite/animated_sprite_parser.cpp
|
source/core/rendering/sprite/animated_sprite_parser.cpp
|
||||||
|
source/core/rendering/effects/heat_haze.cpp
|
||||||
|
source/core/rendering/effects/scan_reveal.cpp
|
||||||
|
source/core/rendering/effects/shadow.cpp
|
||||||
|
source/core/rendering/transitions/mosaic.cpp
|
||||||
|
source/core/rendering/transitions/fade_to_black.cpp
|
||||||
source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp
|
source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp
|
||||||
source/core/rendering/sdl3gpu/viewport.cpp
|
source/core/rendering/sdl3gpu/viewport.cpp
|
||||||
source/core/rendering/sdl3gpu/pipelines/crtpi_pipeline.cpp
|
source/core/rendering/sdl3gpu/pipelines/crtpi_pipeline.cpp
|
||||||
@@ -99,28 +107,39 @@ set(APP_SOURCES
|
|||||||
source/core/resources/resource_pack.cpp
|
source/core/resources/resource_pack.cpp
|
||||||
source/core/resources/palette_loader.cpp
|
source/core/resources/palette_loader.cpp
|
||||||
source/utils/easing.cpp
|
source/utils/easing.cpp
|
||||||
|
source/utils/log.cpp
|
||||||
source/utils/utils.cpp
|
source/utils/utils.cpp
|
||||||
source/game/debug_config.cpp
|
source/game/debug_config.cpp
|
||||||
|
source/game/gameplay_config.cpp
|
||||||
source/game/options.cpp
|
source/game/options.cpp
|
||||||
source/game/options_apply.cpp
|
source/game/options_apply.cpp
|
||||||
source/game/ui/service_menu.cpp
|
source/game/ui/service_menu.cpp
|
||||||
source/game/ui/hud.cpp
|
source/game/ui/hud.cpp
|
||||||
source/game/scenes/placeholder_input.cpp
|
source/game/scenes/placeholder_input.cpp
|
||||||
|
source/game/scenes/start_input.cpp
|
||||||
source/game/scenes/logo_scene.cpp
|
source/game/scenes/logo_scene.cpp
|
||||||
source/game/scenes/title_scene.cpp
|
source/game/scenes/title_scene.cpp
|
||||||
source/game/scenes/intro_scene.cpp
|
source/game/scenes/intro_scene.cpp
|
||||||
source/game/scenes/game_scene.cpp
|
source/game/scenes/game_scene.cpp
|
||||||
source/game/scenes/room_fsm.cpp
|
source/game/scenes/room_fsm.cpp
|
||||||
|
source/game/scenes/game_over_fsm.cpp
|
||||||
source/game/entities/player.cpp
|
source/game/entities/player.cpp
|
||||||
source/game/map/map.cpp
|
source/game/map/map.cpp
|
||||||
source/game/map/tilemap.cpp
|
source/game/map/tilemap.cpp
|
||||||
source/game/map/tilemap_writer.cpp
|
source/game/map/tilemap_writer.cpp
|
||||||
|
# Writer surgical de claus dins de `geometry:` (door_col), paral·lel
|
||||||
|
# al TilemapWriter. Només Debug.
|
||||||
|
source/game/map/map_writer.cpp
|
||||||
source/game/map/paint_layer.cpp
|
source/game/map/paint_layer.cpp
|
||||||
source/game/levels/level_manager.cpp
|
source/game/levels/level_manager.cpp
|
||||||
# Mòdul editor (només activa contingut en Debug via `#ifdef _DEBUG`).
|
# Mòdul editor (només activa contingut en Debug via `#ifdef _DEBUG`).
|
||||||
# En Release el fitxer compila a un object buit i l'enllaçador no
|
# En Release els fitxers compilen a object buit i l'enllaçador no
|
||||||
# arrossega cap símbol del joc final.
|
# arrossega cap símbol del joc final.
|
||||||
source/game/editor/editor.cpp
|
source/game/editor/editor.cpp
|
||||||
|
source/game/editor/editor_config.cpp
|
||||||
|
# Writer del bloc `entities:` del YAML del nivell, paral·lel al
|
||||||
|
# TilemapWriter pero per a la persistència de l'editor d'entitats.
|
||||||
|
source/game/entities/entity_writer.cpp
|
||||||
${ENTITY_SOURCES}
|
${ENTITY_SOURCES}
|
||||||
# Fitxer només del binari principal: `loadFromLevel` depèn de
|
# Fitxer només del binari principal: `loadFromLevel` depèn de
|
||||||
# Resource::Cache (→ Surface → GIF → àudio). Separat per no arrossegar
|
# Resource::Cache (→ Surface → GIF → àudio). Separat per no arrossegar
|
||||||
@@ -206,8 +225,10 @@ target_link_libraries(${PROJECT_NAME} PRIVATE SDL3::SDL3)
|
|||||||
add_executable(pack_resources EXCLUDE_FROM_ALL
|
add_executable(pack_resources EXCLUDE_FROM_ALL
|
||||||
tools/pack_resources/pack_resources.cpp
|
tools/pack_resources/pack_resources.cpp
|
||||||
source/core/resources/resource_pack.cpp
|
source/core/resources/resource_pack.cpp
|
||||||
|
source/utils/log.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(pack_resources PRIVATE "${CMAKE_SOURCE_DIR}/source")
|
target_include_directories(pack_resources PRIVATE "${CMAKE_SOURCE_DIR}/source")
|
||||||
|
target_link_libraries(pack_resources PRIVATE SDL3::SDL3)
|
||||||
target_compile_options(pack_resources PRIVATE -Wall -Wextra -Wpedantic)
|
target_compile_options(pack_resources PRIVATE -Wall -Wextra -Wpedantic)
|
||||||
|
|
||||||
# --- REGENERACIÓ AUTOMÀTICA DE build/resources.pack ---
|
# --- REGENERACIÓ AUTOMÀTICA DE build/resources.pack ---
|
||||||
@@ -348,9 +369,12 @@ option(BUILD_TESTS "Build smoke tests" ON)
|
|||||||
if(BUILD_TESTS)
|
if(BUILD_TESTS)
|
||||||
add_executable(test_entities_smoke
|
add_executable(test_entities_smoke
|
||||||
tests/test_entities_smoke.cpp
|
tests/test_entities_smoke.cpp
|
||||||
|
tests/hole_player_stubs.cpp
|
||||||
|
tests/audio_cache_stubs.cpp
|
||||||
source/core/resources/resource_helper.cpp
|
source/core/resources/resource_helper.cpp
|
||||||
source/core/resources/resource_pack.cpp
|
source/core/resources/resource_pack.cpp
|
||||||
source/game/map/map.cpp
|
source/game/map/map.cpp
|
||||||
|
source/utils/log.cpp
|
||||||
${ENTITY_SOURCES_BASE}
|
${ENTITY_SOURCES_BASE}
|
||||||
)
|
)
|
||||||
target_include_directories(test_entities_smoke PRIVATE
|
target_include_directories(test_entities_smoke PRIVATE
|
||||||
@@ -359,6 +383,10 @@ if(BUILD_TESTS)
|
|||||||
)
|
)
|
||||||
target_link_libraries(test_entities_smoke PRIVATE SDL3::SDL3)
|
target_link_libraries(test_entities_smoke PRIVATE SDL3::SDL3)
|
||||||
target_compile_options(test_entities_smoke PRIVATE -Wall -Wextra -Wpedantic)
|
target_compile_options(test_entities_smoke PRIVATE -Wall -Wextra -Wpedantic)
|
||||||
|
# GCC 14 + -O3 + fkyaml header-only inlinia profundament std::map::clear i
|
||||||
|
# dispara fals positius -Warray-bounds dins <bits/stl_tree.h>. El warning és
|
||||||
|
# del codi de tercers (libstdc++ vist a través de fkyaml), no del test.
|
||||||
|
target_compile_options(test_entities_smoke PRIVATE -Wno-array-bounds)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_test(NAME entities_smoke
|
add_test(NAME entities_smoke
|
||||||
COMMAND test_entities_smoke
|
COMMAND test_entities_smoke
|
||||||
@@ -371,9 +399,13 @@ if(BUILD_TESTS)
|
|||||||
add_executable(test_whip_attack
|
add_executable(test_whip_attack
|
||||||
tests/test_whip_attack.cpp
|
tests/test_whip_attack.cpp
|
||||||
tests/whip_attack_player_stubs.cpp
|
tests/whip_attack_player_stubs.cpp
|
||||||
|
tests/hole_player_stubs.cpp
|
||||||
|
tests/audio_cache_stubs.cpp
|
||||||
source/core/resources/resource_helper.cpp
|
source/core/resources/resource_helper.cpp
|
||||||
source/core/resources/resource_pack.cpp
|
source/core/resources/resource_pack.cpp
|
||||||
|
source/game/gameplay_config.cpp
|
||||||
source/game/map/map.cpp
|
source/game/map/map.cpp
|
||||||
|
source/utils/log.cpp
|
||||||
${ENTITY_SOURCES_BASE}
|
${ENTITY_SOURCES_BASE}
|
||||||
source/game/entities/concrete/whip_attack.cpp
|
source/game/entities/concrete/whip_attack.cpp
|
||||||
)
|
)
|
||||||
@@ -398,6 +430,7 @@ if(BUILD_TESTS)
|
|||||||
source/core/input/key_config.cpp
|
source/core/input/key_config.cpp
|
||||||
source/core/resources/resource_helper.cpp
|
source/core/resources/resource_helper.cpp
|
||||||
source/core/resources/resource_pack.cpp
|
source/core/resources/resource_pack.cpp
|
||||||
|
source/utils/log.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(test_scene_flow PRIVATE
|
target_include_directories(test_scene_flow PRIVATE
|
||||||
"${CMAKE_SOURCE_DIR}/source"
|
"${CMAKE_SOURCE_DIR}/source"
|
||||||
@@ -437,6 +470,7 @@ if(BUILD_TESTS)
|
|||||||
source/core/resources/resource_helper.cpp
|
source/core/resources/resource_helper.cpp
|
||||||
source/core/resources/resource_pack.cpp
|
source/core/resources/resource_pack.cpp
|
||||||
source/utils/easing.cpp
|
source/utils/easing.cpp
|
||||||
|
source/utils/log.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(test_game_fsm PRIVATE
|
target_include_directories(test_game_fsm PRIVATE
|
||||||
"${CMAKE_SOURCE_DIR}/source"
|
"${CMAKE_SOURCE_DIR}/source"
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Aventures en Egipte ARCADE - JailDesigner
|
||||||
|
|
||||||
|
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||||
|
|
||||||
|
You are free to:
|
||||||
|
- Share — copy and redistribute the material in any medium or format
|
||||||
|
- Adapt — remix, transform, and build upon the material
|
||||||
|
|
||||||
|
Under the following terms:
|
||||||
|
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
|
||||||
|
- NonCommercial — You may not use the material for commercial purposes.
|
||||||
|
- ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
|
||||||
|
|
||||||
|
No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
|
||||||
|
|
||||||
|
To view a copy of this license, visit:
|
||||||
|
https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
PROJECT := aee_2026
|
PROJECT := aee_arcade
|
||||||
BUILDDIR := build
|
BUILDDIR := build
|
||||||
|
|
||||||
# Detecció de plataforma. En Windows CMake defaulteja a "NMake Makefiles"
|
# Detecció de plataforma. En Windows CMake defaulteja a "NMake Makefiles"
|
||||||
@@ -44,7 +44,47 @@ endif
|
|||||||
|
|
||||||
CMAKE_DEFS := -DGIT_HASH=$(GIT_HASH)
|
CMAKE_DEFS := -DGIT_HASH=$(GIT_HASH)
|
||||||
|
|
||||||
.PHONY: all debug release run run-debug clean rebuild show-version pack controllerdb format format-check tidy tidy-fix cppcheck hooks-install help
|
# ==============================================================================
|
||||||
|
# RELEASE — variables d'empaquetat per distribució
|
||||||
|
# ==============================================================================
|
||||||
|
APP_NAME := Aventures en Egipte ARCADE
|
||||||
|
DIST_DIR := dist
|
||||||
|
RELEASE_FOLDER := $(DIST_DIR)/_tmp
|
||||||
|
TARGET_FILE := $(BUILDDIR)/$(PROJECT)
|
||||||
|
RELEASE_FILE := $(RELEASE_FOLDER)/$(PROJECT)
|
||||||
|
|
||||||
|
# Noms dels artefactes finals (amb VERSION i PROJECT)
|
||||||
|
WINDOWS_RELEASE := $(DIST_DIR)/$(PROJECT)-$(VERSION)-win32-x64.zip
|
||||||
|
MACOS_INTEL_RELEASE := $(DIST_DIR)/$(PROJECT)-$(VERSION)-macos-intel.dmg
|
||||||
|
MACOS_APPLE_SILICON_RELEASE := $(DIST_DIR)/$(PROJECT)-$(VERSION)-macos-apple-silicon.dmg
|
||||||
|
LINUX_RELEASE := $(DIST_DIR)/$(PROJECT)-$(VERSION)-linux.tar.gz
|
||||||
|
|
||||||
|
# Variables específiques de Windows (PowerShell). El subst escapa apòstrofs
|
||||||
|
# (' → '') perquè APP_NAMEs amb apòstrof no trenquen el parser de PowerShell.
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
WIN_TARGET_FILE := $(BUILDDIR)/$(APP_NAME)
|
||||||
|
WIN_RELEASE_FILE := $(RELEASE_FOLDER)/$(APP_NAME)
|
||||||
|
WIN_RELEASE_FILE_PS := $(subst ','',$(WIN_RELEASE_FILE))
|
||||||
|
UNAME_S :=
|
||||||
|
else
|
||||||
|
WIN_TARGET_FILE := $(TARGET_FILE)
|
||||||
|
WIN_RELEASE_FILE := $(RELEASE_FILE)
|
||||||
|
WIN_RELEASE_FILE_PS := $(WIN_RELEASE_FILE)
|
||||||
|
UNAME_S := $(shell uname -s)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Helpers cross-platform per crear/esborrar directoris als sub-targets release.
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
RMFILE := del /Q
|
||||||
|
RMDIR := rmdir /S /Q
|
||||||
|
MKDIR := mkdir
|
||||||
|
else
|
||||||
|
RMFILE := rm -f
|
||||||
|
RMDIR := rm -rdf
|
||||||
|
MKDIR := mkdir -p
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: all debug release _windows_release _macos_release _linux_release run run-debug clean rebuild show-version pack controllerdb format format-check tidy tidy-fix cppcheck hooks-install help
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# COMPILACIÓ
|
# COMPILACIÓ
|
||||||
@@ -52,7 +92,7 @@ CMAKE_DEFS := -DGIT_HASH=$(GIT_HASH)
|
|||||||
# Convenció alineada amb ../aee i ../projecte_2026:
|
# Convenció alineada amb ../aee i ../projecte_2026:
|
||||||
# make → Release (binari d'ús normal)
|
# make → Release (binari d'ús normal)
|
||||||
# make debug → Debug (flux complet + `debug.yaml` per triar escena inicial)
|
# make debug → Debug (flux complet + `debug.yaml` per triar escena inicial)
|
||||||
# make release → Release + empaquetat per a distribució (TODO, pendent)
|
# make release → Release + empaquetat per a distribució (zip/dmg/tar.gz segons SO)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@@ -69,11 +109,178 @@ run: all
|
|||||||
run-debug: debug
|
run-debug: debug
|
||||||
@./$(BUILDDIR)/$(PROJECT)
|
@./$(BUILDDIR)/$(PROJECT)
|
||||||
|
|
||||||
# Release + empaquetat per distribució (zip/dmg/tar.gz). De moment només
|
# Release + empaquetat per a distribució: detecta el SO i delega al
|
||||||
# compila amb CMAKE_BUILD_TYPE=Release; l'empaquetat OS-specific està
|
# sub-target corresponent. Cada sub-target compila Release, copia
|
||||||
# pendent (veure Makefile de ../aee com a referència).
|
# resources.pack + binari + assets al RELEASE_FOLDER, i empaqueta el
|
||||||
release: all
|
# resultat a $(DIST_DIR)/.
|
||||||
@echo "TODO: empaquetat per a distribució (zip/dmg/tar.gz) — pendent"
|
release:
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@"$(MAKE)" _windows_release
|
||||||
|
else
|
||||||
|
ifeq ($(UNAME_S),Darwin)
|
||||||
|
@$(MAKE) _macos_release
|
||||||
|
else
|
||||||
|
@$(MAKE) _linux_release
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# RELEASE — Linux (.tar.gz)
|
||||||
|
# ==============================================================================
|
||||||
|
_linux_release:
|
||||||
|
@echo "Creando release para Linux - Version: $(VERSION)"
|
||||||
|
|
||||||
|
# Compila Release (genera shaders, resources.pack i binari)
|
||||||
|
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
|
||||||
|
@cmake --build $(BUILDDIR) -j$(JOBS)
|
||||||
|
|
||||||
|
# Recrea la carpeta temporal (i $(DIST_DIR) si no existeix)
|
||||||
|
@$(MKDIR) "$(DIST_DIR)" 2>/dev/null || true
|
||||||
|
@$(RMDIR) "$(RELEASE_FOLDER)" 2>/dev/null || true
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
|
# Còpia de fitxers (LICENSE condicional — encara no existeix al repo)
|
||||||
|
cp $(BUILDDIR)/resources.pack "$(RELEASE_FOLDER)"
|
||||||
|
cp README.md "$(RELEASE_FOLDER)"
|
||||||
|
cp gamecontrollerdb.txt "$(RELEASE_FOLDER)"
|
||||||
|
@[ -f LICENSE ] && cp LICENSE "$(RELEASE_FOLDER)" || true
|
||||||
|
cp "$(TARGET_FILE)" "$(RELEASE_FILE)"
|
||||||
|
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
||||||
|
|
||||||
|
# Empaqueta a .tar.gz
|
||||||
|
$(RMFILE) "$(LINUX_RELEASE)"
|
||||||
|
tar -czvf "$(LINUX_RELEASE)" -C "$(RELEASE_FOLDER)" .
|
||||||
|
@echo "Release creado: $(LINUX_RELEASE)"
|
||||||
|
|
||||||
|
# Neteja la carpeta temporal
|
||||||
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# RELEASE — Windows (.zip)
|
||||||
|
# ==============================================================================
|
||||||
|
_windows_release:
|
||||||
|
@echo off
|
||||||
|
@echo Creando release para Windows - Version: $(VERSION)
|
||||||
|
|
||||||
|
# Compila Release
|
||||||
|
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
|
||||||
|
@cmake --build $(BUILDDIR) -j$(JOBS)
|
||||||
|
|
||||||
|
# Crea $(DIST_DIR) i recrea la carpeta temporal
|
||||||
|
@powershell -Command "if (-not (Test-Path '$(DIST_DIR)')) {New-Item '$(DIST_DIR)' -ItemType Directory}"
|
||||||
|
@powershell -Command "if (Test-Path '$(RELEASE_FOLDER)') {Remove-Item '$(RELEASE_FOLDER)' -Recurse -Force}"
|
||||||
|
@powershell -Command "if (-not (Test-Path '$(RELEASE_FOLDER)')) {New-Item '$(RELEASE_FOLDER)' -ItemType Directory}"
|
||||||
|
|
||||||
|
# Còpia de fitxers (LICENSE condicional)
|
||||||
|
@powershell -Command "Copy-Item -Path '$(BUILDDIR)/resources.pack' -Destination '$(RELEASE_FOLDER)'"
|
||||||
|
@powershell -Command "if (Test-Path 'LICENSE') { Copy-Item 'LICENSE' -Destination '$(RELEASE_FOLDER)' }"
|
||||||
|
@powershell -Command "Copy-Item 'README.md' -Destination '$(RELEASE_FOLDER)'"
|
||||||
|
@powershell -Command "Copy-Item 'gamecontrollerdb.txt' -Destination '$(RELEASE_FOLDER)'"
|
||||||
|
@powershell -Command "Copy-Item 'release\windows\dll\*.dll' -Destination '$(RELEASE_FOLDER)'"
|
||||||
|
@powershell -Command "Copy-Item -Path '$(TARGET_FILE).exe' -Destination '$(WIN_RELEASE_FILE_PS).exe'"
|
||||||
|
strip -s -R .comment -R .gnu.version "$(WIN_RELEASE_FILE).exe" --strip-unneeded
|
||||||
|
|
||||||
|
# Empaqueta a .zip
|
||||||
|
@powershell -Command "if (Test-Path '$(WINDOWS_RELEASE)') {Remove-Item '$(WINDOWS_RELEASE)'}"
|
||||||
|
@powershell -Command "Compress-Archive -Path '$(RELEASE_FOLDER)/*' -DestinationPath '$(WINDOWS_RELEASE)'"
|
||||||
|
@echo Release creado: $(WINDOWS_RELEASE)
|
||||||
|
|
||||||
|
# Neteja la carpeta temporal
|
||||||
|
@powershell -Command "if (Test-Path '$(RELEASE_FOLDER)') {Remove-Item '$(RELEASE_FOLDER)' -Recurse -Force}"
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# RELEASE — macOS (.dmg per Intel + Apple Silicon)
|
||||||
|
# ==============================================================================
|
||||||
|
_macos_release:
|
||||||
|
@echo "Creando release para macOS - Version: $(VERSION)"
|
||||||
|
|
||||||
|
# Verificar/instal·lar create-dmg si cal
|
||||||
|
@which create-dmg > /dev/null || (echo "Instalando create-dmg..." && brew install create-dmg)
|
||||||
|
|
||||||
|
# Compila la versió Intel (genera shaders, resources.pack i binari)
|
||||||
|
@cmake -S . -B $(BUILDDIR)/intel -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DMACOS_BUNDLE=ON $(CMAKE_DEFS)
|
||||||
|
@cmake --build $(BUILDDIR)/intel -j$(JOBS)
|
||||||
|
|
||||||
|
# Neteja artefactes anteriors
|
||||||
|
$(RMDIR) "$(RELEASE_FOLDER)" 2>/dev/null || true
|
||||||
|
$(RMFILE) tmp.dmg
|
||||||
|
$(RMFILE) "$(DIST_DIR)"/rw.* 2>/dev/null || true
|
||||||
|
$(RMFILE) "$(MACOS_INTEL_RELEASE)"
|
||||||
|
$(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||||
|
|
||||||
|
# Crea l'estructura del bundle .app
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||||
|
|
||||||
|
# Còpia de recursos i metadades del bundle
|
||||||
|
cp $(BUILDDIR)/intel/resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||||
|
cp gamecontrollerdb.txt "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||||
|
cp -R release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
||||||
|
cp release/icons/*.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||||
|
cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents"
|
||||||
|
@[ -f LICENSE ] && cp LICENSE "$(RELEASE_FOLDER)" || true
|
||||||
|
cp README.md "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
|
# Sobreescriu CFBundleShortVersionString i CFBundleVersion al Info.plist amb la VERSION actual
|
||||||
|
@echo "Actualizando Info.plist con versión $(VERSION)..."
|
||||||
|
@RAW_VERSION=$$(echo "$(VERSION)" | sed 's/^v//'); \
|
||||||
|
sed -i '' '/<key>CFBundleShortVersionString<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"; \
|
||||||
|
sed -i '' '/<key>CFBundleVersion<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"
|
||||||
|
|
||||||
|
# Còpia del binari Intel al bundle
|
||||||
|
cp "$(BUILDDIR)/intel/$(PROJECT)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(PROJECT)"
|
||||||
|
|
||||||
|
# Firma ad-hoc del bundle Intel
|
||||||
|
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
|
||||||
|
|
||||||
|
# Empaqueta el .dmg Intel
|
||||||
|
@echo "Creando DMG Intel con iconos de 96x96..."
|
||||||
|
create-dmg \
|
||||||
|
--volname "$(APP_NAME)" \
|
||||||
|
--window-pos 200 120 \
|
||||||
|
--window-size 720 300 \
|
||||||
|
--icon-size 96 \
|
||||||
|
--text-size 12 \
|
||||||
|
--icon "$(APP_NAME).app" 278 102 \
|
||||||
|
--icon "LICENSE" 441 102 \
|
||||||
|
--icon "README.md" 604 102 \
|
||||||
|
--app-drop-link 115 102 \
|
||||||
|
--hide-extension "$(APP_NAME).app" \
|
||||||
|
"$(MACOS_INTEL_RELEASE)" \
|
||||||
|
"$(RELEASE_FOLDER)" || true
|
||||||
|
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
|
||||||
|
|
||||||
|
# Compila la versió Apple Silicon i la posa al mateix bundle
|
||||||
|
@cmake -S . -B $(BUILDDIR)/arm -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DMACOS_BUNDLE=ON $(CMAKE_DEFS)
|
||||||
|
@cmake --build $(BUILDDIR)/arm -j$(JOBS)
|
||||||
|
cp "$(BUILDDIR)/arm/$(PROJECT)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(PROJECT)"
|
||||||
|
|
||||||
|
# Re-firma amb el binari arm64
|
||||||
|
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
|
||||||
|
|
||||||
|
# Empaqueta el .dmg Apple Silicon
|
||||||
|
@echo "Creando DMG Apple Silicon con iconos de 96x96..."
|
||||||
|
create-dmg \
|
||||||
|
--volname "$(APP_NAME)" \
|
||||||
|
--window-pos 200 120 \
|
||||||
|
--window-size 720 300 \
|
||||||
|
--icon-size 96 \
|
||||||
|
--text-size 12 \
|
||||||
|
--icon "$(APP_NAME).app" 278 102 \
|
||||||
|
--icon "LICENSE" 441 102 \
|
||||||
|
--icon "README.md" 604 102 \
|
||||||
|
--app-drop-link 115 102 \
|
||||||
|
--hide-extension "$(APP_NAME).app" \
|
||||||
|
"$(MACOS_APPLE_SILICON_RELEASE)" \
|
||||||
|
"$(RELEASE_FOLDER)" || true
|
||||||
|
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
|
||||||
|
|
||||||
|
# Neteja temporals
|
||||||
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
$(RMDIR) $(BUILDDIR)/intel
|
||||||
|
$(RMDIR) $(BUILDDIR)/arm
|
||||||
|
$(RMFILE) "$(DIST_DIR)"/rw.* 2>/dev/null || true
|
||||||
|
|
||||||
show-version:
|
show-version:
|
||||||
@echo "$(PROJECT) $(VERSION) ($(GIT_HASH))"
|
@echo "$(PROJECT) $(VERSION) ($(GIT_HASH))"
|
||||||
@@ -86,8 +293,14 @@ rebuild: clean all
|
|||||||
# Empaqueta data/ a $(BUILDDIR)/resources.pack (format AE26). Força un rebuild
|
# Empaqueta data/ a $(BUILDDIR)/resources.pack (format AE26). Força un rebuild
|
||||||
# del pack encara que res no hagi canviat dins data/. L'empaquetat també es fa
|
# del pack encara que res no hagi canviat dins data/. L'empaquetat també es fa
|
||||||
# automàticament a cada `make`/`make debug` via el target CMake `resource_pack`.
|
# automàticament a cada `make`/`make debug` via el target CMake `resource_pack`.
|
||||||
|
#
|
||||||
|
# NO passem `-DCMAKE_BUILD_TYPE`: així respectem el tipus ja configurat al
|
||||||
|
# `CMakeCache.txt` (Debug si vens de `make debug`, Release si vens de
|
||||||
|
# `make release`). Si forcéssim Release ací, el següent build de debug
|
||||||
|
# invalidaria la cache i recompilaria-ho tot. El binari `pack_resources`
|
||||||
|
# és una utilitat petita on el build type és irrellevant.
|
||||||
pack:
|
pack:
|
||||||
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
|
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) $(CMAKE_DEFS)
|
||||||
@cmake --build $(BUILDDIR) --target pack_resources
|
@cmake --build $(BUILDDIR) --target pack_resources
|
||||||
@./$(BUILDDIR)/pack_resources data $(BUILDDIR)/resources.pack
|
@./$(BUILDDIR)/pack_resources data $(BUILDDIR)/resources.pack
|
||||||
|
|
||||||
@@ -145,7 +358,7 @@ help:
|
|||||||
@echo " make run-debug - Compilar (Debug) i executar"
|
@echo " make run-debug - Compilar (Debug) i executar"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " Release:"
|
@echo " Release:"
|
||||||
@echo " make release - Release + empaquetat (TODO pendent)"
|
@echo " make release - Release + empaquetat (zip/dmg/tar.gz segons SO)"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " Recursos:"
|
@echo " Recursos:"
|
||||||
@echo " make pack - Empaquetar data/ a $(BUILDDIR)/resources.pack (format AE26)"
|
@echo " make pack - Empaquetar data/ a $(BUILDDIR)/resources.pack (format AE26)"
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Tema visual de l'editor de tilemap (només Debug). Carregat per
|
||||||
|
# EditorConfig a l'arrencada; les claus absents cauen als valors compilats
|
||||||
|
# a Defaults::Editor (veure source/utils/defaults.hpp).
|
||||||
|
|
||||||
|
picker:
|
||||||
|
margin: 8 # px entre canvas i caixa del picker
|
||||||
|
spacing: 1 # px de separació entre tiles dins del picker
|
||||||
|
|
||||||
|
# Colors ARGB en hex. Accepta enter (0xFF2244FF) o cadena ("#FF2244FF").
|
||||||
|
colors:
|
||||||
|
border: "0xFF6A86C8" # vora 1 px que envolta canvas i picker (blau suau)
|
||||||
|
picker_bg: "0xFFC8C0D8" # fons del picker (lavanda clara)
|
||||||
|
picker_hover: "0xFFFFFFFF" # vora 1 px del tile sota el cursor
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# AEE 2026 — Tecles d'UI (Global Inputs)
|
# AEE ARCADE — Tecles d'UI (Global Inputs)
|
||||||
#
|
#
|
||||||
# Mapeig id → codi SDL (el que reconeix SDL_GetScancodeFromName). Les tecles
|
# Mapeig id → codi SDL (el que reconeix SDL_GetScancodeFromName). Les tecles
|
||||||
# de moviment del jugador viuen a part (Defaults::KeysGame); ací només hi ha
|
# de moviment del jugador viuen a part (Defaults::KeysGame); ací només hi ha
|
||||||
@@ -35,18 +35,24 @@ keys:
|
|||||||
- id: toggle_render_info
|
- id: toggle_render_info
|
||||||
code: "F10"
|
code: "F10"
|
||||||
desc: "Cicle de l'overlay de debug: apagat / dalt / baix"
|
desc: "Cicle de l'overlay de debug: apagat / dalt / baix"
|
||||||
- id: pause
|
|
||||||
code: "F11"
|
|
||||||
desc: "Pausa el joc (o botó START del mando)"
|
|
||||||
- id: menu_toggle
|
- id: menu_toggle
|
||||||
code: "F12"
|
code: "F12"
|
||||||
desc: "Obri / tanca el menú de servei"
|
desc: "Obri / tanca el menú de servei"
|
||||||
- id: editor_toggle
|
- id: editor_toggle
|
||||||
code: "9"
|
code: "9"
|
||||||
desc: "Entra/surt del mode editor (només Debug)"
|
desc: "Entra/surt del mode editor (només Debug)"
|
||||||
- id: editor_picker
|
- id: editor_tile_picker
|
||||||
code: "T"
|
code: "T"
|
||||||
desc: "Obri/tanca el tilepicker dins de l'editor"
|
desc: "Obri/tanca el tilepicker dins de l'editor"
|
||||||
|
- id: editor_entity_picker
|
||||||
|
code: "E"
|
||||||
|
desc: "Obri/tanca l'entity picker dins de l'editor"
|
||||||
|
- id: editor_hand
|
||||||
|
code: "H"
|
||||||
|
desc: "Activa el mode mà de l'editor (selecciona/mou/borra entitats)"
|
||||||
|
- id: editor_delete
|
||||||
|
code: "Delete"
|
||||||
|
desc: "Esborra l'entitat seleccionada en mode mà"
|
||||||
- id: prev_room
|
- id: prev_room
|
||||||
code: "["
|
code: "["
|
||||||
desc: "Salta a la sala anterior del levels.yaml (només Debug)"
|
desc: "Salta a la sala anterior del levels.yaml (només Debug)"
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Configuració global del sistema d'il·luminació.
|
||||||
|
#
|
||||||
|
# Cada llum emissora (player, torxa, mòmia, ...) té un únic paràmetre
|
||||||
|
# propi: el radi en píxels. La forma de la llum dins d'aquest radi
|
||||||
|
# (els tres anells del gradient) viu en aquest fitxer perquè és una
|
||||||
|
# decisió de "feel" comuna a totes les entitats — així pots tocar la
|
||||||
|
# corba aquí sense haver de modificar 10 YAMLs.
|
||||||
|
#
|
||||||
|
# Forma del gradient (centre → vora):
|
||||||
|
# 0..inner_ratio del radi → inner_intensity (zona totalment il·luminada)
|
||||||
|
# inner_ratio..mid_ratio → mid_intensity (anell mig)
|
||||||
|
# mid_ratio..1.0 → outer_intensity (anell exterior)
|
||||||
|
# fora del radi → light_level de la sala
|
||||||
|
#
|
||||||
|
# Les intensitats són factors 0..1 que es multipliquen sobre el píxel
|
||||||
|
# final del canvas. inner=1.0 vol dir "píxel sense alterar".
|
||||||
|
gradient:
|
||||||
|
inner_ratio: 0.5
|
||||||
|
mid_ratio: 0.85
|
||||||
|
inner_intensity: 1.0
|
||||||
|
mid_intensity: 0.8
|
||||||
|
outer_intensity: 0.6
|
||||||
|
|
||||||
|
# Modulació del radi quan una entitat declara `flicker: true` al seu
|
||||||
|
# bloc `light:`. El radi efectiu per frame és:
|
||||||
|
# r_eff = r_base + A1·sin(2π·f1·t + φ1) + A2·sin(2π·f2·t + φ2)
|
||||||
|
# on (φ1, φ2) es deriven de la posició de l'emissor per a que cada
|
||||||
|
# antorxa balancegi en una fase diferent (sense estat per emissor).
|
||||||
|
# Combinant dues sinusoides amb freqüències incommensurables s'obté
|
||||||
|
# un patró "fluid" que el ull llegeix com a foc; pujar `noise_*`
|
||||||
|
# aporta més inquietud, baixar-ho fa la flama més serena.
|
||||||
|
flicker:
|
||||||
|
wave_amplitude_px: 2
|
||||||
|
wave_frequency_hz: 3.0
|
||||||
|
noise_amplitude_px: 1
|
||||||
|
noise_frequency_hz: 7.0
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
# Tema de la UI: índexs de paleta, timings, fonts i flags visuals. Tota
|
||||||
|
# clau absent cau al valor compilat a Defaults::UI (veure defaults.hpp).
|
||||||
|
|
||||||
|
colors:
|
||||||
|
render_info_text: 58
|
||||||
|
render_info_shadow: 16
|
||||||
|
canvas_bg: 72
|
||||||
|
notification_text: 232
|
||||||
|
notification_bg: 64
|
||||||
|
exit_text: 71
|
||||||
|
exit_bg: 2
|
||||||
|
menu_bg: 2
|
||||||
|
menu_border: 232
|
||||||
|
menu_title: 237
|
||||||
|
menu_label: 58
|
||||||
|
menu_value: 232
|
||||||
|
menu_cursor: 71
|
||||||
|
menu_disabled: 16
|
||||||
|
hud_bg: 9
|
||||||
|
hud_flash: 63
|
||||||
|
# Rètol de transició de sala (ROOM_INTRO i ROOM_OUTRO). Independents
|
||||||
|
# de notification_* perquè la fase i les notificacions són dos canals
|
||||||
|
# visuals distints: ací pots canviar el color del rètol sense tocar
|
||||||
|
# els missatges del HUD. Comparteix la família del CENTER del HUD
|
||||||
|
# (or sobre marró) perquè "Piràmide N / Sala N" sigui sempre daurat
|
||||||
|
# arreu del joc.
|
||||||
|
room_text: 55 # or brillant (#FFDA00, = hud_center.value)
|
||||||
|
room_text_outline: 10 # marró cremat (#482400, = hud_center.shadow)
|
||||||
|
|
||||||
|
timings:
|
||||||
|
notification_ms: 4000
|
||||||
|
exit_ms: 4000
|
||||||
|
|
||||||
|
fonts:
|
||||||
|
hud:
|
||||||
|
name: "8bithud"
|
||||||
|
gif: "data/fonts/8bithud.gif"
|
||||||
|
fnt: "data/fonts/8bithud.fnt"
|
||||||
|
kerning: 1
|
||||||
|
placeholder:
|
||||||
|
name: "ari-w9500-condensed-display"
|
||||||
|
gif: "data/fonts/ari-w9500-condensed-display.gif"
|
||||||
|
fnt: "data/fonts/ari-w9500-condensed-display.fnt"
|
||||||
|
kerning: 1
|
||||||
|
# Font del rètol de transició de sala (ROOM_INTRO i ROOM_OUTRO).
|
||||||
|
room_text:
|
||||||
|
name: "CaesarDressing-Regular"
|
||||||
|
gif: "data/fonts/CaesarDressing-Regular.gif"
|
||||||
|
fnt: "data/fonts/CaesarDressing-Regular.fnt"
|
||||||
|
kerning: 1
|
||||||
|
menu_title:
|
||||||
|
name: "ari-w9500-display"
|
||||||
|
gif: "data/fonts/ari-w9500-display.gif"
|
||||||
|
fnt: "data/fonts/ari-w9500-display.fnt"
|
||||||
|
kerning: 0
|
||||||
|
menu_items:
|
||||||
|
name: "ari-w9500-condensed-display"
|
||||||
|
gif: "data/fonts/ari-w9500-condensed-display.gif"
|
||||||
|
fnt: "data/fonts/ari-w9500-condensed-display.fnt"
|
||||||
|
kerning: 0
|
||||||
|
# Copyright de la TITLE: pixel-art estricte (Tiny5-Regular size 5,
|
||||||
|
# caixa 3×6 px) generat amb font-gen. Diferenciada de la `placeholder`
|
||||||
|
# que pinta el "press start" — així la jerarquia tipogràfica del peu
|
||||||
|
# queda neta.
|
||||||
|
copyright:
|
||||||
|
name: "Tiny5-Regular"
|
||||||
|
gif: "data/fonts/Tiny5-Regular.gif"
|
||||||
|
fnt: "data/fonts/Tiny5-Regular.fnt"
|
||||||
|
kerning: 1
|
||||||
|
|
||||||
|
hud:
|
||||||
|
bg_enabled: false
|
||||||
|
entry_ms: 800 # durada de l'animació d'entrada dels tres blocs
|
||||||
|
flash_ms: 250 # durada del flash quan un jugador rep un hit
|
||||||
|
shake_ms: 300 # durada del shake que acompanya el flash
|
||||||
|
# Parpadeig dels prompts inactius ("Polsa start..." / "Espera..."). Un
|
||||||
|
# únic temporitzador global al Hud sincronitza P1 i P2 i no es reinicia
|
||||||
|
# quan el text canvia entre CAN_JOIN i WAIT. cycle<=0 o ratio>=1 →
|
||||||
|
# sempre visible (disable trivial).
|
||||||
|
blink_cycle_ms: 1000 # durada del cicle complet
|
||||||
|
blink_visible_ratio: 0.8 # proporció del cicle visible (0..1)
|
||||||
|
|
||||||
|
# Famílies de color del HUD per bloc. Cada bloc té `label` (to apagat
|
||||||
|
# per etiquetes), `value` (to viu per a la xifra) i `shadow` (to fosc
|
||||||
|
# del mateix matís — efecte embossing 1 px a baix-dreta). Si manca un
|
||||||
|
# camp, cau al default compilat a `Defaults::UI`. El `colors.hud_flash`
|
||||||
|
# és comú a totes tres famílies.
|
||||||
|
hud_p1:
|
||||||
|
label: 7 # vermell pur
|
||||||
|
value: 183 # crema-préssec
|
||||||
|
shadow: 2 # vermell fosc
|
||||||
|
hud_center:
|
||||||
|
label: 29 # ambre cremat
|
||||||
|
value: 55 # or brillant
|
||||||
|
shadow: 10 # marró cremat
|
||||||
|
hud_p2:
|
||||||
|
label: 248 # cian pur
|
||||||
|
value: 253 # blau pàl·lid
|
||||||
|
shadow: 64 # blau marí
|
||||||
|
|
||||||
|
# Geometria del popup superior (Notifier). En píxels del canvas, llevat de
|
||||||
|
# slide_ms (durada en ms de l'animació d'entrada i d'eixida; constant
|
||||||
|
# independentment de la mida de la caixa). El padding vertical és asimètric a
|
||||||
|
# propòsit: padding_top > padding_bottom puja una mica el text dins la caixa.
|
||||||
|
# Corbes disponibles: linear, outQuad, inQuad, inOutQuad, outCubic, inCubic.
|
||||||
|
notifier:
|
||||||
|
padding_h: 6
|
||||||
|
padding_top: 4
|
||||||
|
padding_bottom: 3
|
||||||
|
line_gap: 1
|
||||||
|
margin_top: 3
|
||||||
|
border_px: 1
|
||||||
|
slide_ms: 300
|
||||||
|
slide_in_curve: outCubic
|
||||||
|
slide_out_curve: inCubic
|
||||||
|
|
||||||
|
# Sons del menú de servei. Els fitxers viuen a data/audio/sounds/. SELECT
|
||||||
|
# acompanya navegació (amunt/avall) i back; ACCEPT acompanya modificació
|
||||||
|
# d'opció (esquerra/dreta/retorn) o entrada a un submenú.
|
||||||
|
sounds:
|
||||||
|
menu_select: "menu_select.wav"
|
||||||
|
menu_accept: "menu_accept.wav"
|
||||||
|
# Disparat quan un jugador prem START a la TITLE (primera pulsació o
|
||||||
|
# la del segon jugador dins de la finestra de STARTING).
|
||||||
|
player_start: "player_start.wav"
|
||||||
|
# Soroll/scratch sincronitzat amb la fase SCAN de LogoScene (scanline
|
||||||
|
# reveal). Es dispara al constructor de l'escena.
|
||||||
|
logo_glitch: "glitch.wav"
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
name: column
|
||||||
|
type: decoration
|
||||||
|
editable: true
|
||||||
|
# Sub-picker de frames a l'editor: 6 variants (atlas 2×3 de sub-sprites 16×32).
|
||||||
|
editable_variants: true
|
||||||
|
sprite:
|
||||||
|
path: ../debris/column.gif
|
||||||
|
size: [16, 32]
|
||||||
|
# Ancoratge "feet": el tile [col, row] del spawn és la base de la columna.
|
||||||
|
# El sprite de 16×32 sobresurt 16 px cap amunt sense afectar col·lisió ni
|
||||||
|
# z-order (la caixa lògica és el tile inferior).
|
||||||
|
anchor: feet
|
||||||
|
tile_size: [1, 1]
|
||||||
|
collision:
|
||||||
|
size: [16, 16]
|
||||||
|
# Mur infranquejable al salt: el jugador no pot passar pel damunt.
|
||||||
|
height: 999
|
||||||
|
flags:
|
||||||
|
collides: true
|
||||||
|
interactable: false
|
||||||
|
animations:
|
||||||
|
default: { frames: [0], fps: 1, loop: false }
|
||||||
|
After Width: | Height: | Size: 805 B |
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,5 +1,6 @@
|
|||||||
name: door
|
name: door
|
||||||
type: interactable
|
type: interactable
|
||||||
|
editable: true
|
||||||
sprite:
|
sprite:
|
||||||
path: door.gif
|
path: door.gif
|
||||||
size: [48, 32]
|
size: [48, 32]
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 306 B After Width: | Height: | Size: 303 B |
|
After Width: | Height: | Size: 182 B |
@@ -0,0 +1,27 @@
|
|||||||
|
name: hole
|
||||||
|
type: static_hazard
|
||||||
|
editable: true
|
||||||
|
sprite:
|
||||||
|
path: hole.gif
|
||||||
|
size: [16, 16]
|
||||||
|
tile_size: [1, 1]
|
||||||
|
collision:
|
||||||
|
# Forat: ocupa el tile sencer (16×16). `height: 0` deixa que un salt
|
||||||
|
# AIRBORNE el creui sense disparar el contacte (el filtre d'altura de
|
||||||
|
# `checkPlayerCollisions` el descarta quan `jump_z_ > height`). El
|
||||||
|
# bucle de contacte admet l'entitat per `flags.triggers_on_overlap`,
|
||||||
|
# encara que `flags.collides` sigui false.
|
||||||
|
size: [16, 16]
|
||||||
|
height: 0
|
||||||
|
flags:
|
||||||
|
collides: false
|
||||||
|
interactable: false
|
||||||
|
# Avui el loader no llig el bloc `flags:` (és declaratiu); el flag
|
||||||
|
# real es fixa al constructor C++ de `Hole`. Mantenim el camp per
|
||||||
|
# coherència amb la resta de plantilles i per quan es cablege la
|
||||||
|
# lectura genèrica de flags.
|
||||||
|
triggers_on_overlap: true
|
||||||
|
animations:
|
||||||
|
idle: { frames: [0], fps: 1, loop: true }
|
||||||
|
stats:
|
||||||
|
damage: 0
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -1,5 +1,6 @@
|
|||||||
name: mummy
|
name: mummy
|
||||||
type: dynamic_hazard
|
type: dynamic_hazard
|
||||||
|
editable: true
|
||||||
sprite:
|
sprite:
|
||||||
path: mummy.gif
|
path: mummy.gif
|
||||||
size: [16, 32]
|
size: [16, 32]
|
||||||
@@ -18,7 +19,7 @@ collision:
|
|||||||
# jugador amb jump_z > height no col·lisiona amb la momia (la salta
|
# jugador amb jump_z > height no col·lisiona amb la momia (la salta
|
||||||
# per damunt). Amb impulse=240 + gravity=600 el pic ronda els 48 px,
|
# per damunt). Amb impulse=240 + gravity=600 el pic ronda els 48 px,
|
||||||
# així que 24 deixa marge per esquivar amb un salt no perfecte.
|
# així que 24 deixa marge per esquivar amb un salt no perfecte.
|
||||||
height: 24
|
height: 12
|
||||||
flags:
|
flags:
|
||||||
collides: true
|
collides: true
|
||||||
interactable: false
|
interactable: false
|
||||||
@@ -35,10 +36,17 @@ animations:
|
|||||||
walk_north: { frames: [4, 5, 6, 7], fps: 8, loop: true }
|
walk_north: { frames: [4, 5, 6, 7], fps: 8, loop: true }
|
||||||
walk_east: { frames: [8, 9, 10, 11], fps: 8, loop: true }
|
walk_east: { frames: [8, 9, 10, 11], fps: 8, loop: true }
|
||||||
walk_west: { frames: [8, 9, 10, 11], fps: 8, loop: true, flip_h: true }
|
walk_west: { frames: [8, 9, 10, 11], fps: 8, loop: true, flip_h: true }
|
||||||
|
raise: { frames: [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27], fps: 8 , loop: false }
|
||||||
ai:
|
ai:
|
||||||
type: corridor_wanderer
|
type: corridor_wanderer
|
||||||
direction_choice: random
|
direction_choice: random
|
||||||
initial_direction: east
|
initial_direction: east
|
||||||
|
|
||||||
|
# Estat SPAWN: la mòmia s'instancia al pixel_rect_ inicial quan
|
||||||
|
# GameScene crida `spawnPendingActors()` (subfase text-exit de
|
||||||
|
# ROOM_INTRO, fase 4) amb l'animació `raise` activa. La duració del
|
||||||
|
# SPAWN la marca la pròpia animació (no-loop): al `completed()`,
|
||||||
|
# transita a ROAMING i comença a deambular.
|
||||||
stats:
|
stats:
|
||||||
speed: 30
|
speed: 30
|
||||||
damage: 1
|
damage: 1
|
||||||
@@ -57,3 +65,13 @@ hurt:
|
|||||||
duration_ms: 600
|
duration_ms: 600
|
||||||
speed: 60
|
speed: 60
|
||||||
whippable: true
|
whippable: true
|
||||||
|
# So opcional: basename del fitxer dins `data/audio/sounds/`. Es dispara
|
||||||
|
# un sol cop per fuetada quan la mòmia entra a HURT. Si manca, no sona.
|
||||||
|
sound: mummy_hurt.wav
|
||||||
|
|
||||||
|
# Halo tènue al voltant de la mòmia. Radi més curt que el del jugador
|
||||||
|
# perquè el rastre lumínic delati la seva posició sense "il·luminar
|
||||||
|
# la sala" — vol ser una pista visual a la foscor.
|
||||||
|
light:
|
||||||
|
radius: 24
|
||||||
|
flicker: true
|
||||||
@@ -30,20 +30,20 @@ animations:
|
|||||||
stun_east: { frames: [18] }
|
stun_east: { frames: [18] }
|
||||||
stun_west: { frames: [18], flip_h: true }
|
stun_west: { frames: [18], flip_h: true }
|
||||||
|
|
||||||
walk_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
walk_south: { frames: [1, 2, 3, 0], frame_ms: 100 }
|
||||||
walk_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
walk_north: { frames: [5, 6, 7, 4], frame_ms: 100 }
|
||||||
walk_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
walk_east: { frames: [9, 10, 11, 8], frame_ms: 100 }
|
||||||
walk_west: { frames: [8, 9, 10, 11], frame_ms: 100, flip_h: true }
|
walk_west: { frames: [9, 10, 11, 8], frame_ms: 100, flip_h: true }
|
||||||
|
|
||||||
hurt_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
hurt_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
||||||
hurt_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
hurt_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
||||||
hurt_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
hurt_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
||||||
hurt_west: { frames: [8, 9, 10, 11], frame_ms: 100, flip_h: true }
|
hurt_west: { frames: [8, 9, 10, 11], frame_ms: 100, flip_h: true }
|
||||||
|
|
||||||
attack_south: { frames: [20, 21, 22, 23], frame_ms: 50 }
|
attack_south: { frames: [20, 21, 22, 23], frame_ms: 80 }
|
||||||
attack_north: { frames: [24, 25, 26, 27], frame_ms: 50 }
|
attack_north: { frames: [24, 25, 26, 27], frame_ms: 80 }
|
||||||
attack_east: { frames: [28, 29, 30, 31], frame_ms: 50 }
|
attack_east: { frames: [28, 29, 30, 31], frame_ms: 80 }
|
||||||
attack_west: { frames: [28, 29, 30, 31], frame_ms: 50, flip_h: true }
|
attack_west: { frames: [28, 29, 30, 31], frame_ms: 80, flip_h: true }
|
||||||
|
|
||||||
recover_south: { frames: [23] }
|
recover_south: { frames: [23] }
|
||||||
recover_north: { frames: [27] }
|
recover_north: { frames: [27] }
|
||||||
@@ -73,6 +73,13 @@ animations:
|
|||||||
frame_ms: [60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280]
|
frame_ms: [60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280]
|
||||||
loop: false
|
loop: false
|
||||||
|
|
||||||
|
# Mort per caiguda a un agujero (DeathCause::HOLE). `loop: false` perquè
|
||||||
|
# `animationIsCompleted()` dispari el respawn timer determinísticament.
|
||||||
|
death_hole:
|
||||||
|
frames: [15]
|
||||||
|
frame_ms: 60
|
||||||
|
loop: false
|
||||||
|
|
||||||
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
||||||
# tocs curts (passets d'un tile sense rellisquera).
|
# tocs curts (passets d'un tile sense rellisquera).
|
||||||
inertia:
|
inertia:
|
||||||
@@ -90,13 +97,10 @@ turn:
|
|||||||
south_to_north: west
|
south_to_north: west
|
||||||
|
|
||||||
# Salt vertical (px de z, no toca la posició al món).
|
# Salt vertical (px de z, no toca la posició al món).
|
||||||
# `shadow_y_offset`: puja la sombra per compensar la franja
|
|
||||||
# transparent sota els peus del sprite.
|
|
||||||
jump:
|
jump:
|
||||||
impulse: 200
|
impulse: 200
|
||||||
gravity: 600
|
gravity: 600
|
||||||
landing_stun_ms: 400
|
landing_stun_ms: 400
|
||||||
shadow_y_offset: 3
|
|
||||||
sound: jump.wav
|
sound: jump.wav
|
||||||
land_sound: land.wav
|
land_sound: land.wav
|
||||||
|
|
||||||
@@ -112,7 +116,7 @@ hurt:
|
|||||||
# recuperació en què la hitbox ja no fa dany.
|
# recuperació en què la hitbox ja no fa dany.
|
||||||
whip:
|
whip:
|
||||||
range_tiles: 3
|
range_tiles: 3
|
||||||
swing_ms: 200
|
swing_ms: 320
|
||||||
cooldown_ms: 200
|
cooldown_ms: 200
|
||||||
damage: 1
|
damage: 1
|
||||||
sound: whip.wav
|
sound: whip.wav
|
||||||
@@ -124,3 +128,23 @@ whip:
|
|||||||
death:
|
death:
|
||||||
respawn_delay_ms: 500
|
respawn_delay_ms: 500
|
||||||
lives: 3
|
lives: 3
|
||||||
|
|
||||||
|
# Immunitat post-spawn: durant `duration_ms` ms, els hazards no
|
||||||
|
# poden ferir ni matar el jugador (els forats sí que el maten — la
|
||||||
|
# caiguda no és dany convencional). Visualment es manifesta amb un
|
||||||
|
# parpadeig que alterna la paleta normal del sprite amb la paleta
|
||||||
|
# `palette` (basename de `data/entities/player/<name>.pal`) cada
|
||||||
|
# `blink_period_ms` ms. Si `duration_ms` és 0 (o el bloc manca), la
|
||||||
|
# mecànica queda desactivada i el comportament és l'antic.
|
||||||
|
immunity:
|
||||||
|
duration_ms: 3000
|
||||||
|
blink_period_ms: 100
|
||||||
|
palette: morcus_wash
|
||||||
|
|
||||||
|
# Llum emesa pel jugador. `radius` és el radi del cercle de llum
|
||||||
|
# en píxels del canvas; el gradient (3 anells: 1.0 / 0.9 / 0.8) viu
|
||||||
|
# a data/config/lighting.yaml i és compartit per tots els emissors.
|
||||||
|
# Omet el bloc per desactivar la llum d'aquest personatge.
|
||||||
|
light:
|
||||||
|
radius: 64
|
||||||
|
flicker: true
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
JASC-PAL
|
||||||
|
0100
|
||||||
|
16
|
||||||
|
0 0 0 255
|
||||||
|
150 133 88 255
|
||||||
|
253 233 185 255
|
||||||
|
237 215 165 255
|
||||||
|
214 193 145 255
|
||||||
|
255 252 208 255
|
||||||
|
252 234 189 255
|
||||||
|
239 222 176 255
|
||||||
|
175 190 128 255
|
||||||
|
173 175 115 255
|
||||||
|
159 159 104 255
|
||||||
|
246 211 157 255
|
||||||
|
229 192 139 255
|
||||||
|
213 177 127 255
|
||||||
|
243 226 184 255
|
||||||
|
0 0 0 255
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
JASC-PAL
|
||||||
|
0100
|
||||||
|
16
|
||||||
|
0 0 0 255
|
||||||
|
102 118 132 255
|
||||||
|
226 238 247 255
|
||||||
|
206 216 222 255
|
||||||
|
179 190 198 255
|
||||||
|
245 255 255 255
|
||||||
|
223 239 253 255
|
||||||
|
208 224 238 255
|
||||||
|
124 190 178 255
|
||||||
|
125 170 162 255
|
||||||
|
109 151 150 255
|
||||||
|
221 210 210 255
|
||||||
|
200 187 189 255
|
||||||
|
181 169 175 255
|
||||||
|
213 229 247 255
|
||||||
|
0 0 0 255
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
JASC-PAL
|
||||||
|
0100
|
||||||
|
16
|
||||||
|
0 0 0 255
|
||||||
|
190 190 190 255
|
||||||
|
255 255 255 255
|
||||||
|
255 248 239 255
|
||||||
|
239 233 226 255
|
||||||
|
255 255 255 255
|
||||||
|
255 255 255 255
|
||||||
|
254 254 254 255
|
||||||
|
184 244 213 255
|
||||||
|
193 229 202 255
|
||||||
|
184 216 198 255
|
||||||
|
255 242 225 255
|
||||||
|
255 228 213 255
|
||||||
|
251 216 207 255
|
||||||
|
255 255 255 255
|
||||||
|
0 0 0 255
|
||||||
@@ -30,20 +30,20 @@ animations:
|
|||||||
stun_east: { frames: [18] }
|
stun_east: { frames: [18] }
|
||||||
stun_west: { frames: [18], flip_h: true }
|
stun_west: { frames: [18], flip_h: true }
|
||||||
|
|
||||||
walk_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
walk_south: { frames: [1, 2, 3, 0], frame_ms: 100 }
|
||||||
walk_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
walk_north: { frames: [5, 6, 7, 4], frame_ms: 100 }
|
||||||
walk_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
walk_east: { frames: [9, 10, 11, 8], frame_ms: 100 }
|
||||||
walk_west: { frames: [8, 9, 10, 11], frame_ms: 100, flip_h: true }
|
walk_west: { frames: [9, 10, 11, 8], frame_ms: 100, flip_h: true }
|
||||||
|
|
||||||
hurt_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
hurt_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
||||||
hurt_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
hurt_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
||||||
hurt_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
hurt_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
||||||
hurt_west: { frames: [8, 9, 10, 11], frame_ms: 100, flip_h: true }
|
hurt_west: { frames: [8, 9, 10, 11], frame_ms: 100, flip_h: true }
|
||||||
|
|
||||||
attack_south: { frames: [20, 21, 22, 23], frame_ms: 50 }
|
attack_south: { frames: [20, 21, 22, 23], frame_ms: 80 }
|
||||||
attack_north: { frames: [24, 25, 26, 27], frame_ms: 50 }
|
attack_north: { frames: [24, 25, 26, 27], frame_ms: 80 }
|
||||||
attack_east: { frames: [28, 29, 30, 31], frame_ms: 50 }
|
attack_east: { frames: [28, 29, 30, 31], frame_ms: 80 }
|
||||||
attack_west: { frames: [28, 29, 30, 31], frame_ms: 50, flip_h: true }
|
attack_west: { frames: [28, 29, 30, 31], frame_ms: 80, flip_h: true }
|
||||||
|
|
||||||
recover_south: { frames: [23] }
|
recover_south: { frames: [23] }
|
||||||
recover_north: { frames: [27] }
|
recover_north: { frames: [27] }
|
||||||
@@ -73,6 +73,13 @@ animations:
|
|||||||
frame_ms: [60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280]
|
frame_ms: [60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280]
|
||||||
loop: false
|
loop: false
|
||||||
|
|
||||||
|
# Mort per caiguda a un agujero (DeathCause::HOLE). `loop: false` perquè
|
||||||
|
# `animationIsCompleted()` dispari el respawn timer determinísticament.
|
||||||
|
death_hole:
|
||||||
|
frames: [15]
|
||||||
|
frame_ms: 60
|
||||||
|
loop: false
|
||||||
|
|
||||||
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
||||||
# tocs curts (passets d'un tile sense rellisquera).
|
# tocs curts (passets d'un tile sense rellisquera).
|
||||||
inertia:
|
inertia:
|
||||||
@@ -90,13 +97,10 @@ turn:
|
|||||||
south_to_north: west
|
south_to_north: west
|
||||||
|
|
||||||
# Salt vertical (px de z, no toca la posició al món).
|
# Salt vertical (px de z, no toca la posició al món).
|
||||||
# `shadow_y_offset`: puja la sombra per compensar la franja
|
|
||||||
# transparent sota els peus del sprite.
|
|
||||||
jump:
|
jump:
|
||||||
impulse: 200
|
impulse: 200
|
||||||
gravity: 600
|
gravity: 600
|
||||||
landing_stun_ms: 400
|
landing_stun_ms: 400
|
||||||
shadow_y_offset: 3
|
|
||||||
sound: jump.wav
|
sound: jump.wav
|
||||||
land_sound: land.wav
|
land_sound: land.wav
|
||||||
|
|
||||||
@@ -112,7 +116,7 @@ hurt:
|
|||||||
# recuperació en què la hitbox ja no fa dany.
|
# recuperació en què la hitbox ja no fa dany.
|
||||||
whip:
|
whip:
|
||||||
range_tiles: 3
|
range_tiles: 3
|
||||||
swing_ms: 200
|
swing_ms: 320
|
||||||
cooldown_ms: 200
|
cooldown_ms: 200
|
||||||
damage: 1
|
damage: 1
|
||||||
sound: whip.wav
|
sound: whip.wav
|
||||||
@@ -124,3 +128,23 @@ whip:
|
|||||||
death:
|
death:
|
||||||
respawn_delay_ms: 500
|
respawn_delay_ms: 500
|
||||||
lives: 3
|
lives: 3
|
||||||
|
|
||||||
|
# Immunitat post-spawn: durant `duration_ms` ms, els hazards no
|
||||||
|
# poden ferir ni matar el jugador (els forats sí que el maten — la
|
||||||
|
# caiguda no és dany convencional). Visualment es manifesta amb un
|
||||||
|
# parpadeig que alterna la paleta normal del sprite amb la paleta
|
||||||
|
# `palette` (basename de `data/entities/player/<name>.pal`) cada
|
||||||
|
# `blink_period_ms` ms. Si `duration_ms` és 0 (o el bloc manca), la
|
||||||
|
# mecànica queda desactivada i el comportament és l'antic.
|
||||||
|
immunity:
|
||||||
|
duration_ms: 3000
|
||||||
|
blink_period_ms: 100
|
||||||
|
palette: sam_wash
|
||||||
|
|
||||||
|
# Llum emesa pel jugador. `radius` és el radi del cercle de llum
|
||||||
|
# en píxels del canvas; el gradient (3 anells: 1.0 / 0.9 / 0.8) viu
|
||||||
|
# a data/config/lighting.yaml i és compartit per tots els emissors.
|
||||||
|
# Omet el bloc per desactivar la llum d'aquest personatge.
|
||||||
|
light:
|
||||||
|
radius: 64
|
||||||
|
flicker: true
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
JASC-PAL
|
||||||
|
0100
|
||||||
|
16
|
||||||
|
0 0 0 255
|
||||||
|
150 133 88 255
|
||||||
|
202 176 123 255
|
||||||
|
191 165 112 255
|
||||||
|
181 156 103 255
|
||||||
|
217 158 115 255
|
||||||
|
194 142 101 255
|
||||||
|
188 143 98 255
|
||||||
|
214 193 145 255
|
||||||
|
196 176 128 255
|
||||||
|
181 161 115 255
|
||||||
|
246 211 157 255
|
||||||
|
229 192 139 255
|
||||||
|
213 177 127 255
|
||||||
|
243 226 184 255
|
||||||
|
0 0 0 255
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
JASC-PAL
|
||||||
|
0100
|
||||||
|
16
|
||||||
|
0 0 0 255
|
||||||
|
102 118 132 255
|
||||||
|
166 169 171 255
|
||||||
|
152 156 158 255
|
||||||
|
140 144 147 255
|
||||||
|
191 144 160 255
|
||||||
|
161 125 146 255
|
||||||
|
152 127 142 255
|
||||||
|
179 190 198 255
|
||||||
|
157 168 179 255
|
||||||
|
139 151 164 255
|
||||||
|
221 210 210 255
|
||||||
|
200 187 189 255
|
||||||
|
181 169 175 255
|
||||||
|
213 229 247 255
|
||||||
|
0 0 0 255
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
JASC-PAL
|
||||||
|
0100
|
||||||
|
16
|
||||||
|
0 0 0 255
|
||||||
|
190 190 190 255
|
||||||
|
235 220 205 255
|
||||||
|
226 212 197 255
|
||||||
|
219 205 191 255
|
||||||
|
255 194 197 255
|
||||||
|
248 184 193 255
|
||||||
|
238 188 189 255
|
||||||
|
239 233 226 255
|
||||||
|
226 220 216 255
|
||||||
|
214 210 208 255
|
||||||
|
255 242 225 255
|
||||||
|
255 228 213 255
|
||||||
|
251 216 207 255
|
||||||
|
255 255 255 255
|
||||||
|
0 0 0 255
|
||||||
|
Before Width: | Height: | Size: 848 B After Width: | Height: | Size: 1.6 KiB |
@@ -1,5 +1,6 @@
|
|||||||
name: sarcophagus
|
name: sarcophagus
|
||||||
type: interactable
|
type: interactable
|
||||||
|
editable: true
|
||||||
sprite:
|
sprite:
|
||||||
path: sarcophagus.gif
|
path: sarcophagus.gif
|
||||||
size: [48, 32]
|
size: [48, 32]
|
||||||
@@ -19,11 +20,29 @@ flags:
|
|||||||
interactable: true
|
interactable: true
|
||||||
animations:
|
animations:
|
||||||
closed: { frames: [0], fps: 1, loop: true }
|
closed: { frames: [0], fps: 1, loop: true }
|
||||||
opening: { frames: [0], fps: 6, loop: false }
|
opening: { frames: [1, 2], fps: 6, loop: false }
|
||||||
open: { frames: [0], fps: 1, loop: true }
|
open: { frames: [3], fps: 1, loop: true }
|
||||||
behaviour:
|
behaviour:
|
||||||
states: [CLOSED, OPENING, OPEN]
|
states: [CLOSED, OPENING, OPEN]
|
||||||
initial_state: CLOSED
|
initial_state: CLOSED
|
||||||
on_perimeter_complete: OPENING
|
on_perimeter_complete: OPENING
|
||||||
on_opening_end: OPEN
|
on_opening_end: OPEN
|
||||||
emits_event_on_open: sarcophagus_opened
|
emits_event_on_open: sarcophagus_opened
|
||||||
|
# Sons opcionals. `opening` es dispara un sol cop en la transició
|
||||||
|
# CLOSED → OPENING (quan el jugador completa el perímetre). Si la clau
|
||||||
|
# manca, no sona res. El basename val tant de clau al Resource::Cache
|
||||||
|
# com de path (`Defaults::Paths::AUDIO_SOUNDS_DIR + key`).
|
||||||
|
#
|
||||||
|
# `opening_pitch_spread`: variació uniforme del ratio de reproducció
|
||||||
|
# centrada a 1.0. Amb 0.05 cada obertura sona entre 0.95× i 1.05× la
|
||||||
|
# velocitat normal (puja/baixa també el to, efecte arcade clàssic).
|
||||||
|
# 0 ⇒ sempre 1.0 (sense variació).
|
||||||
|
sound:
|
||||||
|
opening: open_sarc.wav
|
||||||
|
opening_pitch_spread: 0.5
|
||||||
|
# Recompensa que rep el jugador que pinta el tile que tanca el perímetre
|
||||||
|
# (el GameScene la reparteix consumint `sarcophagus_opened`). Si es lleva
|
||||||
|
# aquest bloc o un dels camps, el camp absent val 0 i no s'aplica.
|
||||||
|
reward:
|
||||||
|
points: 100
|
||||||
|
treasures: 1
|
||||||
|
After Width: | Height: | Size: 98 B |
@@ -0,0 +1,22 @@
|
|||||||
|
name: stone
|
||||||
|
type: decoration
|
||||||
|
editable: true
|
||||||
|
# Sub-picker de frames a l'editor: ofereix una graella amb les 24 variants
|
||||||
|
# del atlas (6×4 sub-sprites 16×16) per escollir quina representa cada
|
||||||
|
# instància col·locada.
|
||||||
|
editable_variants: true
|
||||||
|
sprite:
|
||||||
|
path: ../debris/stone.gif
|
||||||
|
size: [16, 16]
|
||||||
|
tile_size: [1, 1]
|
||||||
|
collision:
|
||||||
|
size: [16, 16]
|
||||||
|
# Mur infranquejable al salt: el jugador no la pot saltar per damunt.
|
||||||
|
height: 999
|
||||||
|
flags:
|
||||||
|
collides: true
|
||||||
|
interactable: false
|
||||||
|
# Animació "default" amb un sol frame: el spawn YAML pot sobreescriure-la
|
||||||
|
# via `frame: N` per fixar la variant escollida al editor.
|
||||||
|
animations:
|
||||||
|
default: { frames: [0], fps: 1, loop: false }
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
name: torch
|
name: torch
|
||||||
type: decoration
|
type: decoration
|
||||||
|
editable: true
|
||||||
sprite:
|
sprite:
|
||||||
path: torch.gif
|
path: torch.gif
|
||||||
size: [16, 16]
|
size: [16, 16]
|
||||||
@@ -15,3 +16,14 @@ flags:
|
|||||||
# El render clipa cada frame per `anim.currentFrame()` × 16 píxels en Y.
|
# El render clipa cada frame per `anim.currentFrame()` × 16 píxels en Y.
|
||||||
animations:
|
animations:
|
||||||
idle: { frames: [0, 1, 2, 3], fps: 8, loop: true }
|
idle: { frames: [0, 1, 2, 3], fps: 8, loop: true }
|
||||||
|
|
||||||
|
# Cercle de llum centrat a l'antorxa. El radi és en píxels del canvas;
|
||||||
|
# el gradient global (data/config/lighting.yaml) hi posa la forma (3
|
||||||
|
# anells). Amb `flicker: true` el radi efectiu oscil·la per frame
|
||||||
|
# (suma de dues sinusoides amb fase derivada de la posició) per a
|
||||||
|
# que el cercle "respiri" com una flama; els paràmetres del flicker
|
||||||
|
# també viuen al config global. Omet el bloc per fer una antorxa
|
||||||
|
# "apagada".
|
||||||
|
light:
|
||||||
|
radius: 40
|
||||||
|
flicker: true
|
||||||
@@ -25,7 +25,7 @@ sprites:
|
|||||||
# Animació compartida entre les 4 direccions: la seqüència de frames i les
|
# Animació compartida entre les 4 direccions: la seqüència de frames i les
|
||||||
# durades són idèntiques; només canvia quina surface/mida es clipa.
|
# durades són idèntiques; només canvia quina surface/mida es clipa.
|
||||||
# - `frames` : índex de tile dins l'spritesheet (graella deduïda).
|
# - `frames` : índex de tile dins l'spritesheet (graella deduïda).
|
||||||
# - `frame_ms` : durada uniforme per frame; 50 ms × 4 ≈ 200 ms swing.
|
# - `frame_ms` : durada uniforme per frame; 80 ms × 4 = 320 ms swing.
|
||||||
# - `loop: false` : el látigo viu una animació i mor (`markDead`).
|
# - `loop: false` : el látigo viu una animació i mor (`markDead`).
|
||||||
# - `active_frames` : valors dins de `frames` durant els quals la
|
# - `active_frames` : valors dins de `frames` durant els quals la
|
||||||
# hitbox aplica dany. Wind-up (0) i recovery (3) no
|
# hitbox aplica dany. Wind-up (0) i recovery (3) no
|
||||||
@@ -33,6 +33,6 @@ sprites:
|
|||||||
animations:
|
animations:
|
||||||
swing:
|
swing:
|
||||||
frames: [0, 1, 2, 3]
|
frames: [0, 1, 2, 3]
|
||||||
frame_ms: 50
|
frame_ms: 80
|
||||||
loop: false
|
loop: false
|
||||||
active_frames: [1, 2]
|
active_frames: [1, 2]
|
||||||
|
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 311 B |
|
Before Width: | Height: | Size: 378 B After Width: | Height: | Size: 363 B |
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 348 B |
|
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 327 B |
@@ -0,0 +1,133 @@
|
|||||||
|
# Font: Tiny5-Regular — generado desde Tiny5-Regular.ttf size 8
|
||||||
|
# Generado con font_gen.py
|
||||||
|
|
||||||
|
box_width 6
|
||||||
|
box_height 9
|
||||||
|
columns 15
|
||||||
|
|
||||||
|
# codepoint_decimal ancho_visual
|
||||||
|
32 2 # U+0020
|
||||||
|
33 1 # !
|
||||||
|
34 3 # "
|
||||||
|
35 5 # #
|
||||||
|
36 3 # $
|
||||||
|
37 4 # %
|
||||||
|
38 4 # &
|
||||||
|
39 1 # '
|
||||||
|
40 2 # (
|
||||||
|
41 2 # )
|
||||||
|
42 3 # *
|
||||||
|
43 3 # +
|
||||||
|
44 2 # ,
|
||||||
|
45 3 # -
|
||||||
|
46 1 # .
|
||||||
|
47 2 # /
|
||||||
|
48 3 # 0
|
||||||
|
49 2 # 1
|
||||||
|
50 3 # 2
|
||||||
|
51 3 # 3
|
||||||
|
52 3 # 4
|
||||||
|
53 3 # 5
|
||||||
|
54 3 # 6
|
||||||
|
55 3 # 7
|
||||||
|
56 3 # 8
|
||||||
|
57 3 # 9
|
||||||
|
58 1 # :
|
||||||
|
59 2 # ;
|
||||||
|
60 3 # <
|
||||||
|
61 3 # =
|
||||||
|
62 3 # >
|
||||||
|
63 3 # ?
|
||||||
|
64 4 # @
|
||||||
|
65 4 # A
|
||||||
|
66 4 # B
|
||||||
|
67 4 # C
|
||||||
|
68 4 # D
|
||||||
|
69 4 # E
|
||||||
|
70 4 # F
|
||||||
|
71 4 # G
|
||||||
|
72 4 # H
|
||||||
|
73 1 # I
|
||||||
|
74 3 # J
|
||||||
|
75 4 # K
|
||||||
|
76 3 # L
|
||||||
|
77 5 # M
|
||||||
|
78 4 # N
|
||||||
|
79 4 # O
|
||||||
|
80 4 # P
|
||||||
|
81 4 # Q
|
||||||
|
82 4 # R
|
||||||
|
83 4 # S
|
||||||
|
84 3 # T
|
||||||
|
85 4 # U
|
||||||
|
86 3 # V
|
||||||
|
87 5 # W
|
||||||
|
88 3 # X
|
||||||
|
89 3 # Y
|
||||||
|
90 3 # Z
|
||||||
|
91 2 # [
|
||||||
|
92 2 # \
|
||||||
|
93 2 # ]
|
||||||
|
94 3 # ^
|
||||||
|
95 3 # _
|
||||||
|
96 2 # `
|
||||||
|
97 3 # a
|
||||||
|
98 3 # b
|
||||||
|
99 3 # c
|
||||||
|
100 3 # d
|
||||||
|
101 3 # e
|
||||||
|
102 2 # f
|
||||||
|
103 3 # g
|
||||||
|
104 3 # h
|
||||||
|
105 1 # i
|
||||||
|
106 1 # j
|
||||||
|
107 3 # k
|
||||||
|
108 1 # l
|
||||||
|
109 5 # m
|
||||||
|
110 3 # n
|
||||||
|
111 3 # o
|
||||||
|
112 3 # p
|
||||||
|
113 3 # q
|
||||||
|
114 2 # r
|
||||||
|
115 3 # s
|
||||||
|
116 2 # t
|
||||||
|
117 3 # u
|
||||||
|
118 3 # v
|
||||||
|
119 5 # w
|
||||||
|
120 3 # x
|
||||||
|
121 3 # y
|
||||||
|
122 3 # z
|
||||||
|
123 3 # {
|
||||||
|
124 1 # |
|
||||||
|
125 3 # }
|
||||||
|
126 2 # ~
|
||||||
|
192 4 # À
|
||||||
|
193 4 # Á
|
||||||
|
200 4 # È
|
||||||
|
201 4 # É
|
||||||
|
204 2 # Ì
|
||||||
|
205 2 # Í
|
||||||
|
210 4 # Ò
|
||||||
|
211 4 # Ó
|
||||||
|
217 4 # Ù
|
||||||
|
218 4 # Ú
|
||||||
|
209 4 # Ñ
|
||||||
|
199 4 # Ç
|
||||||
|
224 3 # à
|
||||||
|
225 3 # á
|
||||||
|
232 3 # è
|
||||||
|
233 3 # é
|
||||||
|
236 2 # ì
|
||||||
|
237 2 # í
|
||||||
|
242 3 # ò
|
||||||
|
243 3 # ó
|
||||||
|
249 3 # ù
|
||||||
|
250 3 # ú
|
||||||
|
241 3 # ñ
|
||||||
|
231 3 # ç
|
||||||
|
161 1 # ¡
|
||||||
|
191 3 # ¿
|
||||||
|
171 5 # «
|
||||||
|
187 5 # »
|
||||||
|
183 1 # ·
|
||||||
|
169 3 # ©
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -1,8 +1,8 @@
|
|||||||
# Font: ari-w9500-condensed-display — generado desde ari-w9500-condensed-display.ttf size 11
|
# Font: ari-w9500-condensed-display — generado desde ari-w9500-condensed-display.ttf size 11
|
||||||
# Generado con tools/font_gen/font_gen.py
|
# Generado con font_gen.py
|
||||||
|
|
||||||
box_width 12
|
box_width 12
|
||||||
box_height 11
|
box_height 13
|
||||||
columns 15
|
columns 15
|
||||||
|
|
||||||
# codepoint_decimal ancho_visual
|
# codepoint_decimal ancho_visual
|
||||||
@@ -117,7 +117,7 @@ columns 15
|
|||||||
225 7 # á
|
225 7 # á
|
||||||
232 7 # è
|
232 7 # è
|
||||||
233 7 # é
|
233 7 # é
|
||||||
236 4 # ì
|
236 3 # ì
|
||||||
237 3 # í
|
237 3 # í
|
||||||
242 7 # ò
|
242 7 # ò
|
||||||
243 7 # ó
|
243 7 # ó
|
||||||
@@ -127,6 +127,7 @@ columns 15
|
|||||||
231 7 # ç
|
231 7 # ç
|
||||||
161 3 # ¡
|
161 3 # ¡
|
||||||
191 7 # ¿
|
191 7 # ¿
|
||||||
171 10 # «
|
171 7 # «
|
||||||
187 10 # »
|
187 7 # »
|
||||||
183 3 # ·
|
183 3 # ·
|
||||||
|
169 10 # ©
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -1,8 +1,8 @@
|
|||||||
# Font: ari-w9500-display — generado desde ari-w9500-display.ttf size 11
|
# Font: ari-w9500-display — generado desde ari-w9500-display.ttf size 11
|
||||||
# Generado con tools/font_gen/font_gen.py
|
# Generado con font_gen.py
|
||||||
|
|
||||||
box_width 12
|
box_width 12
|
||||||
box_height 11
|
box_height 13
|
||||||
columns 15
|
columns 15
|
||||||
|
|
||||||
# codepoint_decimal ancho_visual
|
# codepoint_decimal ancho_visual
|
||||||
@@ -117,7 +117,7 @@ columns 15
|
|||||||
225 8 # á
|
225 8 # á
|
||||||
232 8 # è
|
232 8 # è
|
||||||
233 8 # é
|
233 8 # é
|
||||||
236 4 # ì
|
236 3 # ì
|
||||||
237 3 # í
|
237 3 # í
|
||||||
242 8 # ò
|
242 8 # ò
|
||||||
243 8 # ó
|
243 8 # ó
|
||||||
@@ -127,6 +127,7 @@ columns 15
|
|||||||
231 8 # ç
|
231 8 # ç
|
||||||
161 3 # ¡
|
161 3 # ¡
|
||||||
191 8 # ¿
|
191 8 # ¿
|
||||||
171 10 # «
|
171 7 # «
|
||||||
187 10 # »
|
187 7 # »
|
||||||
183 3 # ·
|
183 3 # ·
|
||||||
|
169 10 # ©
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -1,4 +1,4 @@
|
|||||||
# AEE 2026 — Català
|
# AEE ARCADE — Català
|
||||||
# lang: ca
|
# lang: ca
|
||||||
|
|
||||||
notification:
|
notification:
|
||||||
@@ -14,7 +14,7 @@ input:
|
|||||||
shader_off: "Shaders desactivats"
|
shader_off: "Shaders desactivats"
|
||||||
vsync_on: "VSync activat"
|
vsync_on: "VSync activat"
|
||||||
vsync_off: "VSync desactivat"
|
vsync_off: "VSync desactivat"
|
||||||
screenshot: "Captura"
|
screenshot: "Imatge {} guardada a {}"
|
||||||
shader: "Shader"
|
shader: "Shader"
|
||||||
preset: "Preset"
|
preset: "Preset"
|
||||||
scaling_disabled: "Escalat sense"
|
scaling_disabled: "Escalat sense"
|
||||||
@@ -23,10 +23,12 @@ input:
|
|||||||
scaling_overscan: "Escalat overscan"
|
scaling_overscan: "Escalat overscan"
|
||||||
scaling_integer: "Escalat enter"
|
scaling_integer: "Escalat enter"
|
||||||
press_again_exit: "Prem una altra volta per eixir"
|
press_again_exit: "Prem una altra volta per eixir"
|
||||||
paused: "Pausa"
|
|
||||||
editor_on: "Editor ON"
|
editor_on: "Editor ON"
|
||||||
editor_off: "Editor OFF"
|
editor_off: "Editor OFF"
|
||||||
editor_save_error: "Editor: error guardant el mapa"
|
editor_save_error: "Editor: error guardant el mapa"
|
||||||
|
editor_keep_door: "Editor: cal almenys una porta"
|
||||||
|
editor_keep_sarc: "Editor: cal almenys un sarcòfag"
|
||||||
|
editor_invalid_level: "Editor: nivell incomplet (porta i sarcs)"
|
||||||
|
|
||||||
hud:
|
hud:
|
||||||
p1: "P1"
|
p1: "P1"
|
||||||
@@ -35,6 +37,17 @@ hud:
|
|||||||
treasures: "Tres"
|
treasures: "Tres"
|
||||||
pyramid: "Piramide"
|
pyramid: "Piramide"
|
||||||
room: "Sala"
|
room: "Sala"
|
||||||
|
# Prompts mostrats al bloc d'un slot inactiu (en lloc dels zeros)
|
||||||
|
# quan un jugador encara no ha pulsat START o ha esgotat vides.
|
||||||
|
# Dues línies per fer-los caber al bloc lateral (~106 px).
|
||||||
|
join_prompt_can_join_l1: "Polsa start"
|
||||||
|
join_prompt_can_join_l2: "per jugar"
|
||||||
|
join_prompt_wait_l1: "Espera"
|
||||||
|
join_prompt_wait_l2: "per jugar"
|
||||||
|
|
||||||
|
# Textos de l'escena TITLE.
|
||||||
|
title:
|
||||||
|
press_start: "Polsa START per a començar"
|
||||||
|
|
||||||
# Textos de la transició d'entrada/sortida de sala (FSM de GameScene).
|
# Textos de la transició d'entrada/sortida de sala (FSM de GameScene).
|
||||||
# Tant l'INTRO com l'OUTRO es renderitzen com a dues línies separades
|
# Tant l'INTRO com l'OUTRO es renderitzen com a dues línies separades
|
||||||
@@ -46,6 +59,12 @@ game:
|
|||||||
room_intro_room: "Sala {r}"
|
room_intro_room: "Sala {r}"
|
||||||
room_complete_line1: "Fase"
|
room_complete_line1: "Fase"
|
||||||
room_complete_line2: "Completada"
|
room_complete_line2: "Completada"
|
||||||
|
# Rètol del game over (sub-FSM de la GameScene). El countdown es
|
||||||
|
# pinta com a segona línia (un enter) durant la fase 1 de
|
||||||
|
# CONTINUE_PROMPT — només cal traduir el rètol superior.
|
||||||
|
continue_prompt: "Continuar?"
|
||||||
|
game_over_line1: "Fi del"
|
||||||
|
game_over_line2: "Joc"
|
||||||
|
|
||||||
menu:
|
menu:
|
||||||
titles:
|
titles:
|
||||||
@@ -55,6 +74,7 @@ menu:
|
|||||||
controls: "Controls"
|
controls: "Controls"
|
||||||
keyboard: "Teclat"
|
keyboard: "Teclat"
|
||||||
gamepad: "Comandament"
|
gamepad: "Comandament"
|
||||||
|
tweaks: "Jugabilitat"
|
||||||
system: "Sistema"
|
system: "Sistema"
|
||||||
labels:
|
labels:
|
||||||
player_1: "Jugador 1"
|
player_1: "Jugador 1"
|
||||||
@@ -66,6 +86,7 @@ menu:
|
|||||||
controls_submenu: "Controls"
|
controls_submenu: "Controls"
|
||||||
keyboard_submenu: "Teclat"
|
keyboard_submenu: "Teclat"
|
||||||
gamepad_submenu: "Comandament"
|
gamepad_submenu: "Comandament"
|
||||||
|
tweaks_submenu: "Jugabilitat"
|
||||||
system_submenu: "Sistema"
|
system_submenu: "Sistema"
|
||||||
move_up: "Amunt"
|
move_up: "Amunt"
|
||||||
move_down: "Avall"
|
move_down: "Avall"
|
||||||
@@ -73,6 +94,7 @@ menu:
|
|||||||
move_right: "Dreta"
|
move_right: "Dreta"
|
||||||
jump: "Saltar"
|
jump: "Saltar"
|
||||||
attack: "Atacar"
|
attack: "Atacar"
|
||||||
|
start: "Start"
|
||||||
service: "Opcions"
|
service: "Opcions"
|
||||||
gamepad_p1: "Comandament P1"
|
gamepad_p1: "Comandament P1"
|
||||||
gamepad_p2: "Comandament P2"
|
gamepad_p2: "Comandament P2"
|
||||||
@@ -93,6 +115,9 @@ menu:
|
|||||||
music_volume: "Volum música"
|
music_volume: "Volum música"
|
||||||
sounds: "Sons"
|
sounds: "Sons"
|
||||||
sounds_volume: "Volum sons"
|
sounds_volume: "Volum sons"
|
||||||
|
whip_pierces_walls: "Látec travessa sarcs"
|
||||||
|
friendly_fire: "Foc amic"
|
||||||
|
players_collide: "Col·lisió entre jugadors"
|
||||||
restart: "Reiniciar"
|
restart: "Reiniciar"
|
||||||
exit_game: "Eixir del joc"
|
exit_game: "Eixir del joc"
|
||||||
values:
|
values:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# AEE 2026 — English
|
# AEE ARCADE — English
|
||||||
# lang: en
|
# lang: en
|
||||||
|
|
||||||
notification:
|
notification:
|
||||||
@@ -14,7 +14,7 @@ input:
|
|||||||
shader_off: "Shaders off"
|
shader_off: "Shaders off"
|
||||||
vsync_on: "VSync on"
|
vsync_on: "VSync on"
|
||||||
vsync_off: "VSync off"
|
vsync_off: "VSync off"
|
||||||
screenshot: "Screenshot"
|
screenshot: "Image {} saved at {}"
|
||||||
shader: "Shader"
|
shader: "Shader"
|
||||||
preset: "Preset"
|
preset: "Preset"
|
||||||
scaling_disabled: "Scaling off"
|
scaling_disabled: "Scaling off"
|
||||||
@@ -23,10 +23,12 @@ input:
|
|||||||
scaling_overscan: "Scaling overscan"
|
scaling_overscan: "Scaling overscan"
|
||||||
scaling_integer: "Scaling integer"
|
scaling_integer: "Scaling integer"
|
||||||
press_again_exit: "Press again to exit"
|
press_again_exit: "Press again to exit"
|
||||||
paused: "Paused"
|
|
||||||
editor_on: "Editor ON"
|
editor_on: "Editor ON"
|
||||||
editor_off: "Editor OFF"
|
editor_off: "Editor OFF"
|
||||||
editor_save_error: "Editor: map save failed"
|
editor_save_error: "Editor: map save failed"
|
||||||
|
editor_keep_door: "Editor: at least one door required"
|
||||||
|
editor_keep_sarc: "Editor: at least one sarcophagus required"
|
||||||
|
editor_invalid_level: "Editor: level incomplete (door and sarcs)"
|
||||||
|
|
||||||
hud:
|
hud:
|
||||||
p1: "P1"
|
p1: "P1"
|
||||||
@@ -35,6 +37,17 @@ hud:
|
|||||||
treasures: "Tre"
|
treasures: "Tre"
|
||||||
pyramid: "Pyramid"
|
pyramid: "Pyramid"
|
||||||
room: "Room"
|
room: "Room"
|
||||||
|
# Prompts shown in an inactive slot's block (instead of zeros) while
|
||||||
|
# a player hasn't pressed START yet or has run out of lives. Two
|
||||||
|
# short lines so they fit in the side block (~106 px wide).
|
||||||
|
join_prompt_can_join_l1: "Press start"
|
||||||
|
join_prompt_can_join_l2: "to play"
|
||||||
|
join_prompt_wait_l1: "Please"
|
||||||
|
join_prompt_wait_l2: "wait"
|
||||||
|
|
||||||
|
# Texts of the TITLE scene.
|
||||||
|
title:
|
||||||
|
press_start: "Press START to begin"
|
||||||
|
|
||||||
# Room transition texts (GameScene FSM intro/outro). Both INTRO and
|
# Room transition texts (GameScene FSM intro/outro). Both INTRO and
|
||||||
# OUTRO render as two independent lines with their own animation.
|
# OUTRO render as two independent lines with their own animation.
|
||||||
@@ -45,6 +58,12 @@ game:
|
|||||||
room_intro_room: "Room {r}"
|
room_intro_room: "Room {r}"
|
||||||
room_complete_line1: "Stage"
|
room_complete_line1: "Stage"
|
||||||
room_complete_line2: "Complete"
|
room_complete_line2: "Complete"
|
||||||
|
# Game over labels (sub-FSM in GameScene). The countdown is drawn as
|
||||||
|
# a numeric second line during CONTINUE_PROMPT phase 1, so only the
|
||||||
|
# top label needs translation.
|
||||||
|
continue_prompt: "Continue?"
|
||||||
|
game_over_line1: "Game"
|
||||||
|
game_over_line2: "Over"
|
||||||
|
|
||||||
menu:
|
menu:
|
||||||
titles:
|
titles:
|
||||||
@@ -54,6 +73,7 @@ menu:
|
|||||||
controls: "Controls"
|
controls: "Controls"
|
||||||
keyboard: "Keyboard"
|
keyboard: "Keyboard"
|
||||||
gamepad: "Gamepad"
|
gamepad: "Gamepad"
|
||||||
|
tweaks: "Gameplay"
|
||||||
system: "System"
|
system: "System"
|
||||||
labels:
|
labels:
|
||||||
player_1: "Player 1"
|
player_1: "Player 1"
|
||||||
@@ -65,6 +85,7 @@ menu:
|
|||||||
controls_submenu: "Controls"
|
controls_submenu: "Controls"
|
||||||
keyboard_submenu: "Keyboard"
|
keyboard_submenu: "Keyboard"
|
||||||
gamepad_submenu: "Gamepad"
|
gamepad_submenu: "Gamepad"
|
||||||
|
tweaks_submenu: "Gameplay"
|
||||||
system_submenu: "System"
|
system_submenu: "System"
|
||||||
move_up: "Up"
|
move_up: "Up"
|
||||||
move_down: "Down"
|
move_down: "Down"
|
||||||
@@ -72,6 +93,7 @@ menu:
|
|||||||
move_right: "Right"
|
move_right: "Right"
|
||||||
jump: "Jump"
|
jump: "Jump"
|
||||||
attack: "Attack"
|
attack: "Attack"
|
||||||
|
start: "Start"
|
||||||
service: "Options"
|
service: "Options"
|
||||||
gamepad_p1: "Gamepad P1"
|
gamepad_p1: "Gamepad P1"
|
||||||
gamepad_p2: "Gamepad P2"
|
gamepad_p2: "Gamepad P2"
|
||||||
@@ -92,6 +114,9 @@ menu:
|
|||||||
music_volume: "Music volume"
|
music_volume: "Music volume"
|
||||||
sounds: "Sounds"
|
sounds: "Sounds"
|
||||||
sounds_volume: "Sound volume"
|
sounds_volume: "Sound volume"
|
||||||
|
whip_pierces_walls: "Whip pierces sarcs"
|
||||||
|
friendly_fire: "Friendly fire"
|
||||||
|
players_collide: "Player collision"
|
||||||
restart: "Restart"
|
restart: "Restart"
|
||||||
exit_game: "Exit game"
|
exit_game: "Exit game"
|
||||||
values:
|
values:
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ tileset: data/tilesets/pyramid_1.gif
|
|||||||
tile_size: 16
|
tile_size: 16
|
||||||
origin: [-8, 0]
|
origin: [-8, 0]
|
||||||
|
|
||||||
|
# Il·luminació base de la sala (0..1). 1.0 = sala totalment il·luminada
|
||||||
|
# (com hui, sense efecte visual); 0.0 = completament negra fora del radi
|
||||||
|
# d'un emissor. El gradient dels cercles d'emissor viu a
|
||||||
|
# data/config/lighting.yaml. Omet aquesta clau per deixar la sala neta.
|
||||||
|
light_level: 0.25
|
||||||
|
|
||||||
# Índex de tile amb què cada jugador deixa rastre en trepitjar un sòl
|
# Índex de tile amb què cada jugador deixa rastre en trepitjar un sòl
|
||||||
# pintable. Un índex per jugador perquè a multijugador local el recorregut
|
# pintable. Un índex per jugador perquè a multijugador local el recorregut
|
||||||
# es distingeix a simple vista. Provisional fins que l'art del pintat
|
# es distingeix a simple vista. Provisional fins que l'art del pintat
|
||||||
@@ -82,16 +88,12 @@ data:
|
|||||||
# d'obertura (262/263). La momia al corredor central. L'antorxa al costat
|
# d'obertura (262/263). La momia al corredor central. L'antorxa al costat
|
||||||
# superior esquerre per verificar render d'una entitat decorativa.
|
# superior esquerre per verificar render d'una entitat decorativa.
|
||||||
entities:
|
entities:
|
||||||
- type: torch
|
|
||||||
position: [4, 2]
|
|
||||||
- type: torch
|
- type: torch
|
||||||
position: [8, 2]
|
position: [8, 2]
|
||||||
- type: torch
|
- type: torch
|
||||||
position: [12, 2]
|
position: [12, 2]
|
||||||
- type: torch
|
- type: torch
|
||||||
position: [16, 2]
|
position: [16, 2]
|
||||||
- type: sarcophagus
|
|
||||||
sarc_position: [0, 0]
|
|
||||||
- type: sarcophagus
|
- type: sarcophagus
|
||||||
sarc_position: [1, 0]
|
sarc_position: [1, 0]
|
||||||
- type: sarcophagus
|
- type: sarcophagus
|
||||||
@@ -118,8 +120,6 @@ entities:
|
|||||||
sarc_position: [0, 3]
|
sarc_position: [0, 3]
|
||||||
- type: sarcophagus
|
- type: sarcophagus
|
||||||
sarc_position: [1, 3]
|
sarc_position: [1, 3]
|
||||||
- type: sarcophagus
|
|
||||||
sarc_position: [2, 3]
|
|
||||||
- type: sarcophagus
|
- type: sarcophagus
|
||||||
sarc_position: [3, 3]
|
sarc_position: [3, 3]
|
||||||
- type: sarcophagus
|
- type: sarcophagus
|
||||||
@@ -130,11 +130,33 @@ entities:
|
|||||||
sarc_position: [2, 4]
|
sarc_position: [2, 4]
|
||||||
- type: sarcophagus
|
- type: sarcophagus
|
||||||
sarc_position: [3, 4]
|
sarc_position: [3, 4]
|
||||||
|
- type: torch
|
||||||
|
position: [4, 2]
|
||||||
- type: door
|
- type: door
|
||||||
# Sense `position`: la porta sempre viu al mur trasser. La columna
|
- type: column
|
||||||
# transitable la dicta `geometry.door_col`; el render i la caixa
|
position: [3, 4]
|
||||||
# de col·lisió es deriven d'aquesta dada al loadFromLevel.
|
frame: 2
|
||||||
|
- type: stone
|
||||||
|
position: [5, 4]
|
||||||
|
frame: 16
|
||||||
|
- type: stone
|
||||||
|
position: [4, 4]
|
||||||
|
frame: 19
|
||||||
|
- type: column
|
||||||
|
position: [13, 10]
|
||||||
|
frame: 4
|
||||||
|
- type: stone
|
||||||
|
position: [12, 10]
|
||||||
|
frame: 13
|
||||||
|
- type: stone
|
||||||
|
position: [11, 10]
|
||||||
|
frame: 23
|
||||||
|
- type: hole
|
||||||
|
position: [5, 9]
|
||||||
|
- type: hole
|
||||||
|
position: [9, 11]
|
||||||
|
- type: stone
|
||||||
|
position: [10, 10]
|
||||||
|
frame: 18
|
||||||
- type: mummy
|
- type: mummy
|
||||||
position: [10, 7]
|
position: [10, 13]
|
||||||
- type: mummy
|
|
||||||
position: [7, 9]
|
|
||||||
@@ -131,9 +131,6 @@ entities:
|
|||||||
- type: sarcophagus
|
- type: sarcophagus
|
||||||
sarc_position: [3, 4]
|
sarc_position: [3, 4]
|
||||||
- type: door
|
- type: door
|
||||||
# Sense `position`: la porta sempre viu al mur trasser. La columna
|
|
||||||
# transitable la dicta `geometry.door_col`; el render i la caixa
|
|
||||||
# de col·lisió es deriven d'aquesta dada al loadFromLevel.
|
|
||||||
- type: mummy
|
- type: mummy
|
||||||
position: [10, 7]
|
position: [10, 7]
|
||||||
- type: mummy
|
- type: mummy
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
# Configuració de la GameScene: timings i corbes de la FSM de sala
|
|
||||||
# (ROOM_INTRO i ROOM_OUTRO). Tots els valors són ms i tota la geometria
|
|
||||||
# i font del text es reutilitzen del tema UI (data/ui.yaml > pause +
|
|
||||||
# notification). Si manca el fitxer o alguna clau, GameScene cau als
|
|
||||||
# fallbacks compilats; veure `readSceneConfig` a game_scene.cpp.
|
|
||||||
|
|
||||||
room_intro:
|
|
||||||
fade_in_ms: 500 # negre opac → món visible
|
|
||||||
text_delay_ms: 500 # espera amb el món net abans de sortir el text
|
|
||||||
text_enter_ms: 400 # text esquerra → centre
|
|
||||||
text_hold_ms: 2000 # text quiet al centre
|
|
||||||
text_exit_ms: 400 # text centre → fora per l'esquerra
|
|
||||||
line_gap_px: -4 # px extra entre les dues línies (piràmide / sala)
|
|
||||||
# Delays d'spawn aeri **mesurats des de la fi de la música d'INTRO**
|
|
||||||
# (callback `Audio::setOnMusicEnded`). 0 = cau al moment exacte que
|
|
||||||
# `room_intro.ogg` acaba; valors > 0 escalonen els jugadors. En mode
|
|
||||||
# single-player s'usa només `player_spawn_delay_ms`.
|
|
||||||
player_spawn_delay_ms: 0
|
|
||||||
player2_spawn_delay_ms: 300
|
|
||||||
# Preset de reverb (catàleg a `data/sounds.yaml`) aplicat al primer
|
|
||||||
# LAND de cada jugador durant la cinemàtica d'entrada. La sala dona
|
|
||||||
# "més detall" sonor a l'INTRO; els salts del joc i els respawns
|
|
||||||
# post-mort cauen al so sec. Buit o absent = sense reverb.
|
|
||||||
land_reverb: stone_hall
|
|
||||||
|
|
||||||
room_outro:
|
|
||||||
text_enter_ms: 400
|
|
||||||
text_hold_ms: 2000
|
|
||||||
text_exit_ms: 400
|
|
||||||
fade_out_ms: 500 # món visible → negre opac
|
|
||||||
line_gap_px: -4 # px extra entre les dues línies (fase / completada)
|
|
||||||
black_hold_ms: 500 # pausa en negre abans d'entrar a la pròxima sala
|
|
||||||
|
|
||||||
text:
|
|
||||||
# Noms d'easing tal com els resol UiConfig::curveByName (vegeu
|
|
||||||
# `data/ui.yaml`). El text entra suau i surt accelerant.
|
|
||||||
enter_curve: outCubic
|
|
||||||
exit_curve: inCubic
|
|
||||||
|
|
||||||
# Panel translúcid pintat sota el rètol de transició (INTRO i OUTRO).
|
|
||||||
# Va centrat verticalment al centre del playfield i ocupa tota
|
|
||||||
# l'amplada del canvas. Creix d'altura amb la mateixa enter_curve del
|
|
||||||
# text i decreix amb l'exit_curve. `color` són tres canals RGB (0..255);
|
|
||||||
# `alpha` és la transparència del blend (0 = invisible, 255 = opac).
|
|
||||||
text_panel:
|
|
||||||
color: [36, 182, 170]
|
|
||||||
alpha: 128
|
|
||||||
height_px: 32
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# Configuració de la GameScene: timings i corbes de la FSM de sala
|
||||||
|
# (ROOM_INTRO i ROOM_OUTRO). Tots els valors són ms i tota la geometria
|
||||||
|
# i font del text es reutilitzen del tema UI (data/config/ui.yaml >
|
||||||
|
# notification). Si manca el fitxer o alguna clau, GameScene cau als
|
||||||
|
# fallbacks compilats; veure `readSceneConfig` a game_scene.cpp.
|
||||||
|
|
||||||
|
room_intro:
|
||||||
|
fade_in_ms: 500 # negre opac → món visible
|
||||||
|
text_delay_ms: 500 # espera amb el món net abans de sortir el text
|
||||||
|
text_enter_ms: 400 # text esquerra → centre
|
||||||
|
text_hold_ms: 2000 # text quiet al centre
|
||||||
|
text_exit_ms: 400 # text centre → fora per l'esquerra
|
||||||
|
line_gap_px: -4 # px extra entre les dues línies (piràmide / sala)
|
||||||
|
# Delays d'spawn aeri **mesurats des de la fi de la música d'INTRO**
|
||||||
|
# (callback `Audio::setOnMusicEnded`). 0 = cau al moment exacte que
|
||||||
|
# `room_intro.ogg` acaba; valors > 0 escalonen els jugadors. En mode
|
||||||
|
# single-player s'usa només `player_spawn_delay_ms`.
|
||||||
|
player_spawn_delay_ms: 0
|
||||||
|
player2_spawn_delay_ms: 300
|
||||||
|
# Preset de reverb (catàleg a `data/config/sounds.yaml`) aplicat al primer
|
||||||
|
# LAND de cada jugador durant la cinemàtica d'entrada. La sala dona
|
||||||
|
# "més detall" sonor a l'INTRO; els salts del joc i els respawns
|
||||||
|
# post-mort cauen al so sec. Buit o absent = sense reverb.
|
||||||
|
land_reverb: stone_hall
|
||||||
|
|
||||||
|
room_outro:
|
||||||
|
text_enter_ms: 400
|
||||||
|
text_hold_ms: 2000
|
||||||
|
text_exit_ms: 400
|
||||||
|
fade_out_ms: 500 # món visible → negre opac
|
||||||
|
line_gap_px: -4 # px extra entre les dues línies (fase / completada)
|
||||||
|
black_hold_ms: 500 # pausa en negre abans d'entrar a la pròxima sala
|
||||||
|
|
||||||
|
text:
|
||||||
|
# Noms d'easing tal com els resol UiConfig::curveByName (vegeu
|
||||||
|
# `data/config/ui.yaml`). El text entra suau i surt accelerant.
|
||||||
|
enter_curve: outCubic
|
||||||
|
exit_curve: inCubic
|
||||||
|
|
||||||
|
# Panel translúcid pintat sota el rètol de transició (INTRO i OUTRO).
|
||||||
|
# Va centrat verticalment al centre del playfield i ocupa tota
|
||||||
|
# l'amplada del canvas. Creix d'altura amb la mateixa enter_curve del
|
||||||
|
# text i decreix amb l'exit_curve. `color` són tres canals RGB (0..255);
|
||||||
|
# `alpha` és la transparència del blend (0 = invisible, 255 = opac).
|
||||||
|
text_panel:
|
||||||
|
# Violeta cerimonial: contrasta amb l'or del text (room_text), no
|
||||||
|
# compite amb el blau del bloc P2 del HUD, i deixa la sorra de les
|
||||||
|
# sales respirar al darrere.
|
||||||
|
color: [72, 36, 85]
|
||||||
|
alpha: 160
|
||||||
|
height_px: 32
|
||||||
|
|
||||||
|
# Sub-FSM de game over: dispara CONTINUE? quan tots els jugadors
|
||||||
|
# queden fora de partida durant PLAYING, fa countdown, i si ningú
|
||||||
|
# pulsa START acaba en GAME OVER + fade-to-black + transició a LOGO.
|
||||||
|
# Tots els valors són ms (excepte `continue_count_steps`, que és el
|
||||||
|
# nombre de tics visibles del countdown). Si manca el fitxer o alguna
|
||||||
|
# clau, GameScene cau als fallbacks compilats (vegeu `GameOverFsm::Config`).
|
||||||
|
game_over:
|
||||||
|
# CONTINUE? — animació d'entrada i sortida idèntica al room text.
|
||||||
|
continue_text_enter_ms: 400
|
||||||
|
# Hold del countdown: 10 s = (continue_count_start + 1) graons d'1 s.
|
||||||
|
# La sèrie visible és [continue_count_start, ..., 1, 0]; el "0" es
|
||||||
|
# manté l'últim segon abans del salt a GAME OVER.
|
||||||
|
continue_text_hold_ms: 10000
|
||||||
|
continue_text_exit_ms: 400
|
||||||
|
continue_count_start: 9
|
||||||
|
# GAME OVER — apareix sense enter anim (panel ja amunt del CONTINUE?),
|
||||||
|
# es manté un temps i marxa amb la mateixa exit anim del room text.
|
||||||
|
game_over_text_hold_ms: 1500
|
||||||
|
game_over_text_exit_ms: 400
|
||||||
|
game_over_wait_ms: 400
|
||||||
|
# Fade final cap a LOGO. `black_hold_ms` és la pausa en negre opac
|
||||||
|
# abans que el GameScene demani la transició d'escena.
|
||||||
|
fade_out_ms: 500
|
||||||
|
black_hold_ms: 500
|
||||||
|
# Velocitat (frequency ratio) de la música mentre dura el countdown
|
||||||
|
# de CONTINUE_PROMPT. 1.0 = sense canvi, 1.5 = un 50% més ràpid (i
|
||||||
|
# amb el to més agut: efecte arcade clàssic). Es restableix a 1.0 al
|
||||||
|
# sortir del prompt — tant si el jugador reviu com si entra GAME OVER.
|
||||||
|
continue_music_speed: 1.05
|
||||||
|
# Pista de música que sona durant l'estat GAME_OVER (sense loop).
|
||||||
|
# La fase de hold del text es sincronitza amb la durada real de la
|
||||||
|
# pista, així que el rètol "Fi del Joc" es manté visible mentre dura
|
||||||
|
# la música; després ve l'exit anim, el wait i el fade a LOGO.
|
||||||
|
game_over_music_track: "game_over.ogg"
|
||||||
|
# So que sona cada vegada que apareix un nou número del countdown
|
||||||
|
# (al primer cop que es mostra `continue_count_start`, a cada canvi,
|
||||||
|
# i quan apareix el 0 — però NO al saltar a GAME OVER). Buit = silenci.
|
||||||
|
countdown_sound_key: "countdown.wav"
|
||||||
|
# Llindar a partir del qual qualsevol botó de salt o atac de
|
||||||
|
# qualsevol jugador avança al següent número del countdown.
|
||||||
|
# 7 → skip habilitat mentre el número visible és 7..1 (no a 0).
|
||||||
|
# -1 = mai. Útil per accelerar la decisió un cop la urgència ja
|
||||||
|
# és evident al jugador.
|
||||||
|
skip_below_or_equal: 7
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Configuració de la LogoScene (logotip de l'editora). El revelat del
|
||||||
|
# logo a la fase SCAN imita un escaneig CRT: una banda lluminosa baixa
|
||||||
|
# de dalt a baix; per damunt es veu la imatge ja "impressa", per sota
|
||||||
|
# encara és negre. Al voltant de la banda hi ha glitch (offset
|
||||||
|
# horitzontal de files amb falloff per distància) i ocasionalment
|
||||||
|
# apareixen bursts VHS (franges desplaçades) damunt la part ja
|
||||||
|
# revelada. Quan la banda toca el peu del logo, un flash blanc tanca
|
||||||
|
# l'efecte i s'entra a MIDDLE (logo estable).
|
||||||
|
logo:
|
||||||
|
scan:
|
||||||
|
duration_ms: 1500 # durada total del scan top→bottom
|
||||||
|
band_height_px: 4 # alçada (px) de la banda lluminosa
|
||||||
|
band_alpha: 200 # opacitat (0..255) de la capa blanca de la banda
|
||||||
|
band_pulse_hz: 20.0 # freqüència del pulse de brillantor (Hz)
|
||||||
|
band_pulse_depth: 0.45 # profunditat del pulse (0..1; 0 = sense pulse)
|
||||||
|
# Glitch d'impacte (files al voltant de la banda)
|
||||||
|
glitch_amplitude_px: 6 # offset horitzontal màxim a la banda
|
||||||
|
glitch_band_radius_px: 12 # files damunt/sota la banda amb glitch (falloff lineal)
|
||||||
|
# Bursts VHS sobre la part ja revelada
|
||||||
|
vhs_burst_per_sec: 3 # bursts/segon mitjà
|
||||||
|
vhs_burst_duration_ms: 80 # durada de cada burst
|
||||||
|
vhs_burst_height_px: 8 # alçada de la franja afectada
|
||||||
|
vhs_burst_amplitude_px: 8 # offset horitzontal del burst
|
||||||
|
flash_ms: 100 # flash blanc final quan acaba el scan
|
||||||
|
After Width: | Height: | Size: 494 B |
|
After Width: | Height: | Size: 200 B |
|
After Width: | Height: | Size: 99 B |
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,77 @@
|
|||||||
|
# Configuració de la TitleScene.
|
||||||
|
# `bg_color` i `text_color` són índexs sobre la paleta "ui" (uzebox.pal):
|
||||||
|
# 1 = (36,0,0) gairebé negre amb un mínim de càlid; 31 = (255,109,0)
|
||||||
|
# taronja pur. `duration_ms` és el timeout abans de saltar a la
|
||||||
|
# següent escena (skipable amb tecla no reservada). Els dos
|
||||||
|
# `blink_*_ms` defineixen el cicle del prompt "press start": el text
|
||||||
|
# es veu durant `visible_ms` i s'amaga durant `hidden_ms` repetint-se.
|
||||||
|
title:
|
||||||
|
duration_ms: 30000
|
||||||
|
bg_color: 1
|
||||||
|
text_color: 31
|
||||||
|
# Color del text del © de copyright (peu de la TITLE). Off-white càlid:
|
||||||
|
# índex 183 = (255,218,170), tipus crema/peach, ~90% blanc amb tint càlid.
|
||||||
|
copyright_color: 183
|
||||||
|
# Color de l'outline del prompt "PRESS START". Marró fosc càlid (índex
|
||||||
|
# 19 = 109,72,0), coherent amb la paleta del logo. Es manté separat de
|
||||||
|
# `copyright_color` perquè l'outline i el text del © tenen rols visuals
|
||||||
|
# diferents (contrast vs. peu informatiu).
|
||||||
|
press_start_outline_color: 19
|
||||||
|
# Posicions Y dels tres elements verticals de la TITLE, en percentatge
|
||||||
|
# sobre l'alçada del canvas (240 px). El logo s'ancora pel seu top
|
||||||
|
# (la imatge cau cap avall des d'aquest Y); el prompt i el copyright
|
||||||
|
# es centren verticalment sobre la línia.
|
||||||
|
logo_y_percent: 15
|
||||||
|
prompt_y_percent: 68
|
||||||
|
copyright_y_percent: 92
|
||||||
|
# Separació vertical en píxels entre el minilogo i el text del © al peu.
|
||||||
|
mini_logo_gap_px: 2
|
||||||
|
blink_visible_ms: 800
|
||||||
|
blink_hidden_ms: 200
|
||||||
|
# Fase STARTING (entre la primera pulsació de START i el salt a la
|
||||||
|
# següent escena). `starting_ms` és la durada fixa; durant aquesta
|
||||||
|
# fase el parpadeig accelera per `starting_blink_speedup` (2.0 = doble
|
||||||
|
# de freqüència). Si l'altre jugador prem START dins d'aquesta
|
||||||
|
# finestra, el comptador es reseteja i s'arrenca amb BOTH.
|
||||||
|
starting_ms: 3000
|
||||||
|
# Durant STARTING el prompt commuta a un cicle simètric 50/50
|
||||||
|
# (visible/ocult) amb aquest període total. 200 ms = 5 Hz, prou
|
||||||
|
# ràpid per llegir-se com a "pulsació confirmada".
|
||||||
|
starting_blink_period_ms: 200
|
||||||
|
# Fade-out estil "mosaic dissolve" durant l'última part de STARTING.
|
||||||
|
# `fade_out_ms` ha de ser <= starting_ms (els últims X ms del STARTING
|
||||||
|
# es fan amb el dissolve actiu fins a quedar negre). `fade_out_max_block`
|
||||||
|
# és la mida màxima de bloc en píxels al final del fade.
|
||||||
|
fade_out_ms: 800
|
||||||
|
fade_out_max_block: 32
|
||||||
|
# Fade-out de `title.ogg` en entrar a STARTING. Independent del visual:
|
||||||
|
# la música pot acabar abans o després del mosaic dissolve.
|
||||||
|
music_fade_out_ms: 3000
|
||||||
|
# Fade-to-black per a la sortida d'attract (timeout cap a LOGO). NO és
|
||||||
|
# mosaic — capa negra lineal damunt del canvas. La música no es toca:
|
||||||
|
# `title.ogg` continua sonant cap a LOGO, que ja veurà què en fa.
|
||||||
|
attract_fade_to_black_ms: 800
|
||||||
|
# Seqüència d'aparició dels elements de la TITLE en fase IDLE. Tots
|
||||||
|
# els temps són absoluts des de l'entrada a l'escena. `fade_in_ms` és
|
||||||
|
# la capa negra inicial que s'esvaeix cap al fons; els altres marquen
|
||||||
|
# quan apareix cada element. Si l'usuari prem START en qualsevol
|
||||||
|
# moment, la seqüència es completa instantàniament.
|
||||||
|
intro:
|
||||||
|
fade_in_ms: 500 # fade-in negre inicial sobre el fons
|
||||||
|
game_logo_at_ms: 1500 # visibilitat binària del game_logo
|
||||||
|
mini_logo_at_ms: 2000 # inici del slide-in del mini-logo
|
||||||
|
mini_logo_slide_ms: 500 # durada del slide
|
||||||
|
copyright_at_ms: 2200 # inici del slide-in del copyright
|
||||||
|
copyright_slide_ms: 500 # durada del slide
|
||||||
|
slide_curve: outCubic # corba compartida per mini_logo i copyright
|
||||||
|
press_start_at_ms: 3000 # quan apareix PRESS START amb parpadeig
|
||||||
|
# Distorsió sinusoidal del fons (efecte de calor del desert).
|
||||||
|
# `amplitude_px`: desplaçament màxim de cada fila en píxels.
|
||||||
|
# `wavelength_px`: distància vertical entre dos pics de l'ona.
|
||||||
|
# `speed_hz`: velocitat amb què avança la fase (cicles per segon).
|
||||||
|
# Si `enabled` és false, el fons es pinta sense distorsió.
|
||||||
|
heat_haze:
|
||||||
|
enabled: true
|
||||||
|
amplitude_px: 1.5
|
||||||
|
wavelength_px: 32.0
|
||||||
|
speed_hz: 0.6
|
||||||
|
After Width: | Height: | Size: 17 KiB |
@@ -1,77 +0,0 @@
|
|||||||
# Tema de la UI: índexs de paleta, timings, fonts i flags visuals. Tota
|
|
||||||
# clau absent cau al valor compilat a Defaults::UI (veure defaults.hpp).
|
|
||||||
|
|
||||||
colors:
|
|
||||||
render_info_text: 58
|
|
||||||
render_info_shadow: 16
|
|
||||||
canvas_bg: 72
|
|
||||||
notification_text: 232
|
|
||||||
notification_bg: 64
|
|
||||||
exit_text: 71
|
|
||||||
exit_bg: 2
|
|
||||||
menu_bg: 2
|
|
||||||
menu_border: 232
|
|
||||||
menu_title: 237
|
|
||||||
menu_label: 58
|
|
||||||
menu_value: 232
|
|
||||||
menu_cursor: 71
|
|
||||||
menu_disabled: 16
|
|
||||||
hud_bg: 9
|
|
||||||
hud_label: 58
|
|
||||||
hud_value: 187
|
|
||||||
hud_flash: 237
|
|
||||||
# Rètol de transició de sala (ROOM_INTRO i ROOM_OUTRO). Independents
|
|
||||||
# de notification_* perquè la fase i les notificacions són dos canals
|
|
||||||
# visuals distints: ací pots canviar el color del rètol sense tocar
|
|
||||||
# els missatges del HUD.
|
|
||||||
room_text: 160
|
|
||||||
room_text_outline: 253
|
|
||||||
|
|
||||||
timings:
|
|
||||||
notification_ms: 4000
|
|
||||||
exit_ms: 4000
|
|
||||||
|
|
||||||
fonts:
|
|
||||||
hud:
|
|
||||||
name: "8bithud"
|
|
||||||
gif: "data/fonts/8bithud.gif"
|
|
||||||
fnt: "data/fonts/8bithud.fnt"
|
|
||||||
kerning: 1
|
|
||||||
placeholder:
|
|
||||||
name: "ari-w9500-condensed-display"
|
|
||||||
gif: "data/fonts/ari-w9500-condensed-display.gif"
|
|
||||||
fnt: "data/fonts/ari-w9500-condensed-display.fnt"
|
|
||||||
kerning: 1
|
|
||||||
# Font del rètol de transició de sala (ROOM_INTRO i ROOM_OUTRO).
|
|
||||||
room_text:
|
|
||||||
name: "CaesarDressing-Regular"
|
|
||||||
gif: "data/fonts/CaesarDressing-Regular.gif"
|
|
||||||
fnt: "data/fonts/CaesarDressing-Regular.fnt"
|
|
||||||
kerning: 1
|
|
||||||
menu_title:
|
|
||||||
name: "ari-w9500-display"
|
|
||||||
gif: "data/fonts/ari-w9500-display.gif"
|
|
||||||
fnt: "data/fonts/ari-w9500-display.fnt"
|
|
||||||
kerning: 0
|
|
||||||
menu_items:
|
|
||||||
name: "ari-w9500-condensed-display"
|
|
||||||
gif: "data/fonts/ari-w9500-condensed-display.gif"
|
|
||||||
fnt: "data/fonts/ari-w9500-condensed-display.fnt"
|
|
||||||
kerning: 0
|
|
||||||
|
|
||||||
hud:
|
|
||||||
bg_enabled: false
|
|
||||||
entry_ms: 800 # durada de l'animació d'entrada dels tres blocs
|
|
||||||
flash_ms: 250 # durada del flash quan un jugador rep un hit
|
|
||||||
shake_ms: 300 # durada del shake que acompanya el flash
|
|
||||||
|
|
||||||
# Pausa graduada de la GameScene: el món no para d'un colp, s'atura amb
|
|
||||||
# easing i torna a arrancar amb una altra corba. Els timings es poden
|
|
||||||
# afinar independentment, i les corbes permeten estils diferents entrant
|
|
||||||
# i sortint (p.ex. frenar suau i arrancar seca). Corbes disponibles:
|
|
||||||
# linear, outQuad, inQuad, inOutQuad, outCubic, inCubic.
|
|
||||||
pause:
|
|
||||||
enter_ms: 400
|
|
||||||
exit_ms: 250
|
|
||||||
enter_curve: outCubic
|
|
||||||
exit_curve: inCubic
|
|
||||||
@@ -22,8 +22,8 @@ real (logo animat, menú de títol, cutscene).
|
|||||||
Fitxer personal de desenvolupament, **fora del repo**. Viu a la mateixa carpeta
|
Fitxer personal de desenvolupament, **fora del repo**. Viu a la mateixa carpeta
|
||||||
de sistema que `config.yaml`:
|
de sistema que `config.yaml`:
|
||||||
|
|
||||||
- Linux (XDG): `$XDG_CONFIG_HOME/jailgames/aee_2026/debug.yaml`
|
- Linux (XDG): `$XDG_CONFIG_HOME/jailgames/aee_arcade/debug.yaml`
|
||||||
- Per defecte: `~/.config/jailgames/aee_2026/debug.yaml`
|
- Per defecte: `~/.config/jailgames/aee_arcade/debug.yaml`
|
||||||
|
|
||||||
### Comportament segons build
|
### Comportament segons build
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Sistema d'entitats
|
# Sistema d'entitats
|
||||||
|
|
||||||
Registre del disseny, els treballs fets i els pendents per al sistema d'entitats (sarcòfags, porta, momia, antorxa, trampes, roca) d'aee_2026. Material de referència per a decisions futures — no és documentació d'API.
|
Registre del disseny, els treballs fets i els pendents per al sistema d'entitats (sarcòfags, porta, momia, antorxa, trampes, roca) d'aee_arcade. Material de referència per a decisions futures — no és documentació d'API.
|
||||||
|
|
||||||
Estats possibles: `DONE`, `WIP`, `DEFERRED`, `WONTFIX`.
|
Estats possibles: `DONE`, `WIP`, `DEFERRED`, `WONTFIX`.
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ Estats possibles: `DONE`, `WIP`, `DEFERRED`, `WONTFIX`.
|
|||||||
|
|
||||||
## 1. Context i objectiu inicial
|
## 1. Context i objectiu inicial
|
||||||
|
|
||||||
aee_2026 és un clon tipus Oh Mummy! amb estètica Amidar. Els sarcòfags eren fins ara rectangles purament geomètrics calculats a [Map::getSarcRect](../source/game/map/map.cpp#L67); no hi havia entitats de joc (momies, antorxes, trampes, portes).
|
aee_arcade és un clon tipus Oh Mummy! amb estètica Amidar. Els sarcòfags eren fins ara rectangles purament geomètrics calculats a [Map::getSarcRect](../source/game/map/map.cpp#L67); no hi havia entitats de joc (momies, antorxes, trampes, portes).
|
||||||
|
|
||||||
**Objectiu inicial** (prompt de partida):
|
**Objectiu inicial** (prompt de partida):
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ Al CMakeLists: `ENTITY_SOURCES` conté els fitxers core; `APP_SOURCES` afegeix `
|
|||||||
- `make build`: OK, 0 warnings nous.
|
- `make build`: OK, 0 warnings nous.
|
||||||
- `./build/test_entities_smoke`: **9/9 OK**.
|
- `./build/test_entities_smoke`: **9/9 OK**.
|
||||||
- `ctest --output-on-failure`: 1/1 suite passed.
|
- `ctest --output-on-failure`: 1/1 suite passed.
|
||||||
- `timeout 5 xvfb-run ./build/aee_2026`: 5s sense crash, stdout inclou:
|
- `timeout 5 xvfb-run ./build/aee_arcade`: 5s sense crash, stdout inclou:
|
||||||
```
|
```
|
||||||
Surface : torch.gif ... LOADED
|
Surface : torch.gif ... LOADED
|
||||||
Surface : sarcophagus.gif ... LOADED (×2)
|
Surface : sarcophagus.gif ... LOADED (×2)
|
||||||
@@ -323,7 +323,7 @@ Dos events encadenats perquè el *pintat* no és la *presència*: es filtra per
|
|||||||
|
|
||||||
- `make debug` net, sense warnings ni de clang-tidy ni de cppcheck als fitxers nous.
|
- `make debug` net, sense warnings ni de clang-tidy ni de cppcheck als fitxers nous.
|
||||||
- `./build/test_entities_smoke`: **ALL OK** (14/14). T9 adaptat (publica `tile_painted` en lloc d'`on_tile_entered`); la resta de tests del sistema d'entitats passen sense tocar.
|
- `./build/test_entities_smoke`: **ALL OK** (14/14). T9 adaptat (publica `tile_painted` en lloc d'`on_tile_entered`); la resta de tests del sistema d'entitats passen sense tocar.
|
||||||
- `timeout 5 xvfb-run ./build/aee_2026`: arrenca, log `PaintLayer: 21x15 tiles (336x240 px), tileset data/tilesets/tomb.gif` després de `EntityManager: 27 entitats carregades`, surt amb `Bye!` sense crash.
|
- `timeout 5 xvfb-run ./build/aee_arcade`: arrenca, log `PaintLayer: 21x15 tiles (336x240 px), tileset data/tilesets/tomb.gif` després de `EntityManager: 27 entitats carregades`, surt amb `Bye!` sense crash.
|
||||||
|
|
||||||
### Pendent derivat
|
### Pendent derivat
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Pla d'implementació — Menú de servei
|
# Pla d'implementació — Menú de servei
|
||||||
|
|
||||||
Pla per a portar el menú de servei de `../aee` (`source/core/rendering/menu.cpp`)
|
Pla per a portar el menú de servei de `../aee` (`source/core/rendering/menu.cpp`)
|
||||||
a `aee_2026`, adaptat a l'arquitectura actual (Scenes + Director instanciat +
|
a `aee_arcade`, adaptat a l'arquitectura actual (Scenes + Director instanciat +
|
||||||
`Options` amb setters persistents + `Screen` ARGB + `Text` bitmap). Document de
|
`Options` amb setters persistents + `Screen` ARGB + `Text` bitmap). Document de
|
||||||
referència per a implementar-ho en una sessió futura; no s'ha escrit cap codi
|
referència per a implementar-ho en una sessió futura; no s'ha escrit cap codi
|
||||||
encara.
|
encara.
|
||||||
@@ -33,7 +33,7 @@ Tot el que segueix és la base; la còpia mental serveix per a no reinventar res
|
|||||||
|
|
||||||
## 2. Diferències d'arquitectura rellevants
|
## 2. Diferències d'arquitectura rellevants
|
||||||
|
|
||||||
| Punt | `../aee` | `aee_2026` |
|
| Punt | `../aee` | `aee_arcade` |
|
||||||
| ----------------- | ---------------------------------------------------- | -------------------------------------------------------------------------- |
|
| ----------------- | ---------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||||
| Overlay | `Overlay::render()` dibuixa Menú + Notifier al buffer | No hi ha Overlay. Cada Scene crida `Notifier::render()` i `RenderInfo::render()` |
|
| Overlay | `Overlay::render()` dibuixa Menú + Notifier al buffer | No hi ha Overlay. Cada Scene crida `Notifier::render()` i `RenderInfo::render()` |
|
||||||
| Director | Singleton `Director::get()` amb `requestQuit/requestRestart` | Classe instanciada; sortida via `SDL_EVENT_QUIT` a `EventBuffer` |
|
| Director | Singleton `Director::get()` amb `requestQuit/requestRestart` | Classe instanciada; sortida via `SDL_EVENT_QUIT` a `EventBuffer` |
|
||||||
@@ -223,7 +223,7 @@ es necessita.
|
|||||||
### Limitació: pàgina Controls diferida
|
### Limitació: pàgina Controls diferida
|
||||||
|
|
||||||
El menú de `../aee` té una pàgina Controls (`buildControls`) que permet
|
El menú de `../aee` té una pàgina Controls (`buildControls`) que permet
|
||||||
remappar `up/down/left/right` i la tecla de menú. A `aee_2026`:
|
remappar `up/down/left/right` i la tecla de menú. A `aee_arcade`:
|
||||||
|
|
||||||
- Les tecles de joc són `Defaults::KeysGame::{UP,DOWN,LEFT,RIGHT}` — constants
|
- Les tecles de joc són `Defaults::KeysGame::{UP,DOWN,LEFT,RIGHT}` — constants
|
||||||
`constexpr`, no mutables.
|
`constexpr`, no mutables.
|
||||||
@@ -273,7 +273,7 @@ y, w, h, argb, alpha)` que opere sobre `canvas_.data()`. El canvas és
|
|||||||
fons del menú pot ser `alpha=220` i es veu el joc apagat per darrere.
|
fons del menú pot ser `alpha=220` i es veu el joc apagat per darrere.
|
||||||
|
|
||||||
Mida fixa recomanada per al MVP: `BOX_W = 220`, altura dinàmica (igual que
|
Mida fixa recomanada per al MVP: `BOX_W = 220`, altura dinàmica (igual que
|
||||||
`../aee`). Canvas lògic d'`aee_2026` és `GameCanvas::WIDTH`/`HEIGHT` —
|
`../aee`). Canvas lògic d'`aee_arcade` és `GameCanvas::WIDTH`/`HEIGHT` —
|
||||||
confirmar mida real (mateixos 320×200?) a `utils/defines.hpp` abans de
|
confirmar mida real (mateixos 320×200?) a `utils/defines.hpp` abans de
|
||||||
hardcoded.
|
hardcoded.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def check_dependencies():
|
||||||
|
"""Verifica que ImageMagick esté instalado"""
|
||||||
|
try:
|
||||||
|
subprocess.run(['magick', '--version'], capture_output=True, check=True)
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
print("Error: ImageMagick no está instalado o no se encuentra en el PATH")
|
||||||
|
print("Instala ImageMagick desde: https://imagemagick.org/script/download.php")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Verificar iconutil solo en macOS
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
try:
|
||||||
|
# iconutil no tiene --version, mejor usar which o probar con -h
|
||||||
|
result = subprocess.run(['which', 'iconutil'], capture_output=True, check=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print("✓ iconutil disponible - se crearán archivos .ico e .icns")
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
print("Error: iconutil no está disponible (solo funciona en macOS)")
|
||||||
|
print("Solo se creará el archivo .ico")
|
||||||
|
else:
|
||||||
|
print("ℹ️ Sistema no-macOS detectado - solo se creará archivo .ico")
|
||||||
|
|
||||||
|
|
||||||
|
def create_icons(input_file):
|
||||||
|
"""Crea archivos .icns e .ico a partir de un PNG"""
|
||||||
|
|
||||||
|
# Verificar que el archivo existe
|
||||||
|
if not os.path.isfile(input_file):
|
||||||
|
print(f"Error: El archivo {input_file} no existe.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Obtener información del archivo
|
||||||
|
file_path = Path(input_file)
|
||||||
|
file_dir = file_path.parent
|
||||||
|
file_name = file_path.stem # Nombre sin extensión
|
||||||
|
file_extension = file_path.suffix
|
||||||
|
|
||||||
|
if file_extension.lower() not in ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']:
|
||||||
|
print(f"Advertencia: {file_extension} puede no ser compatible. Se recomienda usar PNG.")
|
||||||
|
|
||||||
|
# Crear archivo .ico usando el método simplificado
|
||||||
|
ico_output = file_dir / f"{file_name}.ico"
|
||||||
|
try:
|
||||||
|
print(f"Creando {ico_output}...")
|
||||||
|
subprocess.run([
|
||||||
|
'magick', str(input_file),
|
||||||
|
'-define', 'icon:auto-resize=256,128,64,48,32,16',
|
||||||
|
str(ico_output)
|
||||||
|
], check=True)
|
||||||
|
print(f"✓ Archivo .ico creado: {ico_output}")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error creando archivo .ico: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Crear archivo .icns (solo en macOS)
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
try:
|
||||||
|
# Crear carpeta temporal para iconset
|
||||||
|
temp_folder = file_dir / "icon.iconset"
|
||||||
|
|
||||||
|
# Eliminar carpeta temporal si existe
|
||||||
|
if temp_folder.exists():
|
||||||
|
shutil.rmtree(temp_folder)
|
||||||
|
|
||||||
|
# Crear carpeta temporal
|
||||||
|
temp_folder.mkdir(parents=True)
|
||||||
|
|
||||||
|
# Definir los tamaños y nombres de archivo para .icns
|
||||||
|
icon_sizes = [
|
||||||
|
(16, "icon_16x16.png"),
|
||||||
|
(32, "icon_16x16@2x.png"),
|
||||||
|
(32, "icon_32x32.png"),
|
||||||
|
(64, "icon_32x32@2x.png"),
|
||||||
|
(128, "icon_128x128.png"),
|
||||||
|
(256, "icon_128x128@2x.png"),
|
||||||
|
(256, "icon_256x256.png"),
|
||||||
|
(512, "icon_256x256@2x.png"),
|
||||||
|
(512, "icon_512x512.png"),
|
||||||
|
(1024, "icon_512x512@2x.png")
|
||||||
|
]
|
||||||
|
|
||||||
|
print("Generando imágenes para .icns...")
|
||||||
|
# Crear cada tamaño de imagen
|
||||||
|
for size, output_name in icon_sizes:
|
||||||
|
output_path = temp_folder / output_name
|
||||||
|
subprocess.run([
|
||||||
|
'magick', str(input_file),
|
||||||
|
'-resize', f'{size}x{size}',
|
||||||
|
str(output_path)
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
# Crear archivo .icns usando iconutil
|
||||||
|
icns_output = file_dir / f"{file_name}.icns"
|
||||||
|
print(f"Creando {icns_output}...")
|
||||||
|
subprocess.run([
|
||||||
|
'iconutil', '-c', 'icns',
|
||||||
|
str(temp_folder),
|
||||||
|
'-o', str(icns_output)
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
# Limpiar carpeta temporal
|
||||||
|
if temp_folder.exists():
|
||||||
|
shutil.rmtree(temp_folder)
|
||||||
|
|
||||||
|
print(f"✓ Archivo .icns creado: {icns_output}")
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error creando archivo .icns: {e}")
|
||||||
|
# Limpiar carpeta temporal en caso de error
|
||||||
|
if temp_folder.exists():
|
||||||
|
shutil.rmtree(temp_folder)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("ℹ️ Archivo .icns no creado (solo disponible en macOS)")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Función principal"""
|
||||||
|
# Verificar argumentos
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print(f"Uso: {sys.argv[0]} ARCHIVO")
|
||||||
|
print("Ejemplo: python3 create_icons.py imagen.png")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
input_file = sys.argv[1]
|
||||||
|
|
||||||
|
# Verificar dependencias
|
||||||
|
check_dependencies()
|
||||||
|
|
||||||
|
# Crear iconos
|
||||||
|
if create_icons(input_file):
|
||||||
|
print("\n✅ Proceso completado exitosamente")
|
||||||
|
else:
|
||||||
|
print("\n❌ El proceso falló")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
After Width: | Height: | Size: 361 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Aventures en Egipte ARCADE</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>aee_arcade</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>icon</string>
|
||||||
|
<key>CFBundleIconName</key>
|
||||||
|
<string>icon</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.jailgames.aee_arcade</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>aee_arcade</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.10</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.10</string>
|
||||||
|
<key>CSResourcesFileMapped</key>
|
||||||
|
<true/>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.15</string>
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright 2026 JailDesigner</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
<key>SUPublicDSAKeyFile</key>
|
||||||
|
<string>dsa_pub.pem</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>AvailableLibraries</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>SDL3.framework/Versions/A/SDL3</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>macos-arm64_x86_64</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>SDL3.framework</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
<string>x86_64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>macos</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>SDL3.framework/SDL3</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>tvos-arm64</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>SDL3.framework</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>tvos</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>SDL3.framework/SDL3</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>ios-arm64</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>SDL3.framework</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>ios</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>SDL3.framework/SDL3</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>ios-arm64_x86_64-simulator</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>SDL3.framework</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
<string>x86_64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>ios</string>
|
||||||
|
<key>SupportedPlatformVariant</key>
|
||||||
|
<string>simulator</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>BinaryPath</key>
|
||||||
|
<string>SDL3.framework/SDL3</string>
|
||||||
|
<key>LibraryIdentifier</key>
|
||||||
|
<string>tvos-arm64_x86_64-simulator</string>
|
||||||
|
<key>LibraryPath</key>
|
||||||
|
<string>SDL3.framework</string>
|
||||||
|
<key>SupportedArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
<string>x86_64</string>
|
||||||
|
</array>
|
||||||
|
<key>SupportedPlatform</key>
|
||||||
|
<string>tvos</string>
|
||||||
|
<key>SupportedPlatformVariant</key>
|
||||||
|
<string>simulator</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>XFWK</string>
|
||||||
|
<key>XCFrameworkFormatVersion</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Headers
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Versions/Current/Resources
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Versions/Current/SDL3
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main include header for the SDL library, version 3.2.20
|
||||||
|
*
|
||||||
|
* It is almost always best to include just this one header instead of
|
||||||
|
* picking out individual headers included here. There are exceptions to
|
||||||
|
* this rule--SDL_main.h is special and not included here--but usually
|
||||||
|
* letting SDL.h include the kitchen sink for you is the correct approach.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_h_
|
||||||
|
#define SDL_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
#include <SDL3/SDL_assert.h>
|
||||||
|
#include <SDL3/SDL_asyncio.h>
|
||||||
|
#include <SDL3/SDL_atomic.h>
|
||||||
|
#include <SDL3/SDL_audio.h>
|
||||||
|
#include <SDL3/SDL_bits.h>
|
||||||
|
#include <SDL3/SDL_blendmode.h>
|
||||||
|
#include <SDL3/SDL_camera.h>
|
||||||
|
#include <SDL3/SDL_clipboard.h>
|
||||||
|
#include <SDL3/SDL_cpuinfo.h>
|
||||||
|
#include <SDL3/SDL_dialog.h>
|
||||||
|
#include <SDL3/SDL_endian.h>
|
||||||
|
#include <SDL3/SDL_error.h>
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
#include <SDL3/SDL_filesystem.h>
|
||||||
|
#include <SDL3/SDL_gamepad.h>
|
||||||
|
#include <SDL3/SDL_gpu.h>
|
||||||
|
#include <SDL3/SDL_guid.h>
|
||||||
|
#include <SDL3/SDL_haptic.h>
|
||||||
|
#include <SDL3/SDL_hidapi.h>
|
||||||
|
#include <SDL3/SDL_hints.h>
|
||||||
|
#include <SDL3/SDL_init.h>
|
||||||
|
#include <SDL3/SDL_iostream.h>
|
||||||
|
#include <SDL3/SDL_joystick.h>
|
||||||
|
#include <SDL3/SDL_keyboard.h>
|
||||||
|
#include <SDL3/SDL_keycode.h>
|
||||||
|
#include <SDL3/SDL_loadso.h>
|
||||||
|
#include <SDL3/SDL_locale.h>
|
||||||
|
#include <SDL3/SDL_log.h>
|
||||||
|
#include <SDL3/SDL_messagebox.h>
|
||||||
|
#include <SDL3/SDL_metal.h>
|
||||||
|
#include <SDL3/SDL_misc.h>
|
||||||
|
#include <SDL3/SDL_mouse.h>
|
||||||
|
#include <SDL3/SDL_mutex.h>
|
||||||
|
#include <SDL3/SDL_pen.h>
|
||||||
|
#include <SDL3/SDL_pixels.h>
|
||||||
|
#include <SDL3/SDL_platform.h>
|
||||||
|
#include <SDL3/SDL_power.h>
|
||||||
|
#include <SDL3/SDL_process.h>
|
||||||
|
#include <SDL3/SDL_properties.h>
|
||||||
|
#include <SDL3/SDL_rect.h>
|
||||||
|
#include <SDL3/SDL_render.h>
|
||||||
|
#include <SDL3/SDL_scancode.h>
|
||||||
|
#include <SDL3/SDL_sensor.h>
|
||||||
|
#include <SDL3/SDL_storage.h>
|
||||||
|
#include <SDL3/SDL_surface.h>
|
||||||
|
#include <SDL3/SDL_system.h>
|
||||||
|
#include <SDL3/SDL_thread.h>
|
||||||
|
#include <SDL3/SDL_time.h>
|
||||||
|
#include <SDL3/SDL_timer.h>
|
||||||
|
#include <SDL3/SDL_tray.h>
|
||||||
|
#include <SDL3/SDL_touch.h>
|
||||||
|
#include <SDL3/SDL_version.h>
|
||||||
|
#include <SDL3/SDL_video.h>
|
||||||
|
#include <SDL3/SDL_oldnames.h>
|
||||||
|
|
||||||
|
#endif /* SDL_h_ */
|
||||||
@@ -0,0 +1,662 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # CategoryAssert
|
||||||
|
*
|
||||||
|
* A helpful assertion macro!
|
||||||
|
*
|
||||||
|
* SDL assertions operate like your usual `assert` macro, but with some added
|
||||||
|
* features:
|
||||||
|
*
|
||||||
|
* - It uses a trick with the `sizeof` operator, so disabled assertions
|
||||||
|
* vaporize out of the compiled code, but variables only referenced in the
|
||||||
|
* assertion won't trigger compiler warnings about being unused.
|
||||||
|
* - It is safe to use with a dangling-else: `if (x) SDL_assert(y); else
|
||||||
|
* do_something();`
|
||||||
|
* - It works the same everywhere, instead of counting on various platforms'
|
||||||
|
* compiler and C runtime to behave.
|
||||||
|
* - It provides multiple levels of assertion (SDL_assert, SDL_assert_release,
|
||||||
|
* SDL_assert_paranoid) instead of a single all-or-nothing option.
|
||||||
|
* - It offers a variety of responses when an assertion fails (retry, trigger
|
||||||
|
* the debugger, abort the program, ignore the failure once, ignore it for
|
||||||
|
* the rest of the program's run).
|
||||||
|
* - It tries to show the user a dialog by default, if possible, but the app
|
||||||
|
* can provide a callback to handle assertion failures however they like.
|
||||||
|
* - It lets failed assertions be retried. Perhaps you had a network failure
|
||||||
|
* and just want to retry the test after plugging your network cable back
|
||||||
|
* in? You can.
|
||||||
|
* - It lets the user ignore an assertion failure, if there's a harmless
|
||||||
|
* problem that one can continue past.
|
||||||
|
* - It lets the user mark an assertion as ignored for the rest of the
|
||||||
|
* program's run; if there's a harmless problem that keeps popping up.
|
||||||
|
* - It provides statistics and data on all failed assertions to the app.
|
||||||
|
* - It allows the default assertion handler to be controlled with environment
|
||||||
|
* variables, in case an automated script needs to control it.
|
||||||
|
* - It can be used as an aid to Clang's static analysis; it will treat SDL
|
||||||
|
* assertions as universally true (under the assumption that you are serious
|
||||||
|
* about the asserted claims and that your debug builds will detect when
|
||||||
|
* these claims were wrong). This can help the analyzer avoid false
|
||||||
|
* positives.
|
||||||
|
*
|
||||||
|
* To use it: compile a debug build and just sprinkle around tests to check
|
||||||
|
* your code!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_assert_h_
|
||||||
|
#define SDL_assert_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The level of assertion aggressiveness.
|
||||||
|
*
|
||||||
|
* This value changes depending on compiler options and other preprocessor
|
||||||
|
* defines.
|
||||||
|
*
|
||||||
|
* It is currently one of the following values, but future SDL releases might
|
||||||
|
* add more:
|
||||||
|
*
|
||||||
|
* - 0: All SDL assertion macros are disabled.
|
||||||
|
* - 1: Release settings: SDL_assert disabled, SDL_assert_release enabled.
|
||||||
|
* - 2: Debug settings: SDL_assert and SDL_assert_release enabled.
|
||||||
|
* - 3: Paranoid settings: All SDL assertion macros enabled, including
|
||||||
|
* SDL_assert_paranoid.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_ASSERT_LEVEL SomeNumberBasedOnVariousFactors
|
||||||
|
|
||||||
|
#elif !defined(SDL_ASSERT_LEVEL)
|
||||||
|
#ifdef SDL_DEFAULT_ASSERT_LEVEL
|
||||||
|
#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
|
||||||
|
#elif defined(_DEBUG) || defined(DEBUG) || \
|
||||||
|
(defined(__GNUC__) && !defined(__OPTIMIZE__))
|
||||||
|
#define SDL_ASSERT_LEVEL 2
|
||||||
|
#else
|
||||||
|
#define SDL_ASSERT_LEVEL 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to tell an attached debugger to pause.
|
||||||
|
*
|
||||||
|
* This allows an app to programmatically halt ("break") the debugger as if it
|
||||||
|
* had hit a breakpoint, allowing the developer to examine program state, etc.
|
||||||
|
*
|
||||||
|
* This is a macro--not a function--so that the debugger breaks on the source
|
||||||
|
* code line that used SDL_TriggerBreakpoint and not in some random guts of
|
||||||
|
* SDL. SDL_assert uses this macro for the same reason.
|
||||||
|
*
|
||||||
|
* If the program is not running under a debugger, SDL_TriggerBreakpoint will
|
||||||
|
* likely terminate the app, possibly without warning. If the current platform
|
||||||
|
* isn't supported, this macro is left undefined.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this macro from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_TriggerBreakpoint() TriggerABreakpointInAPlatformSpecificManner
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1310
|
||||||
|
/* Don't include intrin.h here because it contains C++ code */
|
||||||
|
extern void __cdecl __debugbreak(void);
|
||||||
|
#define SDL_TriggerBreakpoint() __debugbreak()
|
||||||
|
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||||
|
#define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
|
||||||
|
#elif defined(ANDROID)
|
||||||
|
#include <assert.h>
|
||||||
|
#define SDL_TriggerBreakpoint() assert(0)
|
||||||
|
#elif SDL_HAS_BUILTIN(__builtin_debugtrap)
|
||||||
|
#define SDL_TriggerBreakpoint() __builtin_debugtrap()
|
||||||
|
#elif SDL_HAS_BUILTIN(__builtin_trap)
|
||||||
|
#define SDL_TriggerBreakpoint() __builtin_trap()
|
||||||
|
#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
|
||||||
|
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
|
||||||
|
#elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv)
|
||||||
|
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" )
|
||||||
|
#elif ( defined(SDL_PLATFORM_APPLE) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */
|
||||||
|
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
|
||||||
|
#elif defined(SDL_PLATFORM_APPLE) && defined(__arm__)
|
||||||
|
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" )
|
||||||
|
#elif defined(_WIN32) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__arm64__) || defined(__aarch64__)) )
|
||||||
|
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #0xF000\n\t" )
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define SDL_TriggerBreakpoint() __builtin_trap() /* older gcc may not support SDL_HAS_BUILTIN(__builtin_trap) above */
|
||||||
|
#elif defined(__386__) && defined(__WATCOMC__)
|
||||||
|
#define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
|
||||||
|
#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__)
|
||||||
|
#include <signal.h>
|
||||||
|
#define SDL_TriggerBreakpoint() raise(SIGTRAP)
|
||||||
|
#else
|
||||||
|
/* SDL_TriggerBreakpoint is intentionally left undefined on unknown platforms. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro that reports the current function being compiled.
|
||||||
|
*
|
||||||
|
* If SDL can't figure how the compiler reports this, it will use "???".
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_FUNCTION __FUNCTION__
|
||||||
|
|
||||||
|
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
|
||||||
|
# define SDL_FUNCTION __func__
|
||||||
|
#elif ((defined(__GNUC__) && (__GNUC__ >= 2)) || defined(_MSC_VER) || defined (__WATCOMC__))
|
||||||
|
# define SDL_FUNCTION __FUNCTION__
|
||||||
|
#else
|
||||||
|
# define SDL_FUNCTION "???"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro that reports the current file being compiled.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_FILE __FILE__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro that reports the current line number of the file being compiled.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_LINE __LINE__
|
||||||
|
|
||||||
|
/*
|
||||||
|
sizeof (x) makes the compiler still parse the expression even without
|
||||||
|
assertions enabled, so the code is always checked at compile time, but
|
||||||
|
doesn't actually generate code for it, so there are no side effects or
|
||||||
|
expensive checks at run time, just the constant size of what x WOULD be,
|
||||||
|
which presumably gets optimized out as unused.
|
||||||
|
This also solves the problem of...
|
||||||
|
|
||||||
|
int somevalue = blah();
|
||||||
|
SDL_assert(somevalue == 1);
|
||||||
|
|
||||||
|
...which would cause compiles to complain that somevalue is unused if we
|
||||||
|
disable assertions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro for wrapping code in `do {} while (0);` without compiler warnings.
|
||||||
|
*
|
||||||
|
* Visual Studio with really aggressive warnings enabled needs this to avoid
|
||||||
|
* compiler complaints.
|
||||||
|
*
|
||||||
|
* the `do {} while (0);` trick is useful for wrapping code in a macro that
|
||||||
|
* may or may not be a single statement, to avoid various C language
|
||||||
|
* accidents.
|
||||||
|
*
|
||||||
|
* To use:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* do { SomethingOnce(); } while (SDL_NULL_WHILE_LOOP_CONDITION (0));
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_NULL_WHILE_LOOP_CONDITION (0)
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER) /* Avoid /W4 warnings. */
|
||||||
|
/* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking
|
||||||
|
this condition isn't constant. And looks like an owl's face! */
|
||||||
|
#define SDL_NULL_WHILE_LOOP_CONDITION (0,0)
|
||||||
|
#else
|
||||||
|
#define SDL_NULL_WHILE_LOOP_CONDITION (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro used when an assertion is disabled.
|
||||||
|
*
|
||||||
|
* This isn't for direct use by apps, but this is the code that is inserted
|
||||||
|
* when an SDL_assert is disabled (perhaps in a release build).
|
||||||
|
*
|
||||||
|
* The code does nothing, but wraps `condition` in a sizeof operator, which
|
||||||
|
* generates no code and has no side effects, but avoid compiler warnings
|
||||||
|
* about unused variables.
|
||||||
|
*
|
||||||
|
* \param condition the condition to assert (but not actually run here).
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_disabled_assert(condition) \
|
||||||
|
do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible outcomes from a triggered assertion.
|
||||||
|
*
|
||||||
|
* When an enabled assertion triggers, it may call the assertion handler
|
||||||
|
* (possibly one provided by the app via SDL_SetAssertionHandler), which will
|
||||||
|
* return one of these values, possibly after asking the user.
|
||||||
|
*
|
||||||
|
* Then SDL will respond based on this outcome (loop around to retry the
|
||||||
|
* condition, try to break in a debugger, kill the program, or ignore the
|
||||||
|
* problem).
|
||||||
|
*
|
||||||
|
* \since This enum is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef enum SDL_AssertState
|
||||||
|
{
|
||||||
|
SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */
|
||||||
|
SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */
|
||||||
|
SDL_ASSERTION_ABORT, /**< Terminate the program. */
|
||||||
|
SDL_ASSERTION_IGNORE, /**< Ignore the assert. */
|
||||||
|
SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */
|
||||||
|
} SDL_AssertState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about an assertion failure.
|
||||||
|
*
|
||||||
|
* This structure is filled in with information about a triggered assertion,
|
||||||
|
* used by the assertion handler, then added to the assertion report. This is
|
||||||
|
* returned as a linked list from SDL_GetAssertionReport().
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef struct SDL_AssertData
|
||||||
|
{
|
||||||
|
bool always_ignore; /**< true if app should always continue when assertion is triggered. */
|
||||||
|
unsigned int trigger_count; /**< Number of times this assertion has been triggered. */
|
||||||
|
const char *condition; /**< A string of this assert's test code. */
|
||||||
|
const char *filename; /**< The source file where this assert lives. */
|
||||||
|
int linenum; /**< The line in `filename` where this assert lives. */
|
||||||
|
const char *function; /**< The name of the function where this assert lives. */
|
||||||
|
const struct SDL_AssertData *next; /**< next item in the linked list. */
|
||||||
|
} SDL_AssertData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Never call this directly.
|
||||||
|
*
|
||||||
|
* Use the SDL_assert macros instead.
|
||||||
|
*
|
||||||
|
* \param data assert data structure.
|
||||||
|
* \param func function name.
|
||||||
|
* \param file file name.
|
||||||
|
* \param line line number.
|
||||||
|
* \returns assert state.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *data,
|
||||||
|
const char *func,
|
||||||
|
const char *file, int line) SDL_ANALYZER_NORETURN;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro used when an assertion triggers a breakpoint.
|
||||||
|
*
|
||||||
|
* This isn't for direct use by apps; use SDL_assert or SDL_TriggerBreakpoint
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_AssertBreakpoint() SDL_TriggerBreakpoint()
|
||||||
|
|
||||||
|
#elif !defined(SDL_AssertBreakpoint)
|
||||||
|
# if defined(ANDROID) && defined(assert)
|
||||||
|
/* Define this as empty in case assert() is defined as SDL_assert */
|
||||||
|
# define SDL_AssertBreakpoint()
|
||||||
|
# else
|
||||||
|
# define SDL_AssertBreakpoint() SDL_TriggerBreakpoint()
|
||||||
|
# endif
|
||||||
|
#endif /* !SDL_AssertBreakpoint */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro used when an assertion is enabled.
|
||||||
|
*
|
||||||
|
* This isn't for direct use by apps, but this is the code that is inserted
|
||||||
|
* when an SDL_assert is enabled.
|
||||||
|
*
|
||||||
|
* The `do {} while(0)` avoids dangling else problems:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* if (x) SDL_assert(y); else blah();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ... without the do/while, the "else" could attach to this macro's "if". We
|
||||||
|
* try to handle just the minimum we need here in a macro...the loop, the
|
||||||
|
* static vars, and break points. The heavy lifting is handled in
|
||||||
|
* SDL_ReportAssertion().
|
||||||
|
*
|
||||||
|
* \param condition the condition to assert.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_enabled_assert(condition) \
|
||||||
|
do { \
|
||||||
|
while ( !(condition) ) { \
|
||||||
|
static struct SDL_AssertData sdl_assert_data = { false, 0, #condition, NULL, 0, NULL, NULL }; \
|
||||||
|
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
|
||||||
|
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
|
||||||
|
continue; /* go again. */ \
|
||||||
|
} else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
|
||||||
|
SDL_AssertBreakpoint(); \
|
||||||
|
} \
|
||||||
|
break; /* not retrying. */ \
|
||||||
|
} \
|
||||||
|
} while (SDL_NULL_WHILE_LOOP_CONDITION)
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An assertion test that is normally performed only in debug builds.
|
||||||
|
*
|
||||||
|
* This macro is enabled when the SDL_ASSERT_LEVEL is >= 2, otherwise it is
|
||||||
|
* disabled. This is meant to only do these tests in debug builds, so they can
|
||||||
|
* tend to be more expensive, and they are meant to bring everything to a halt
|
||||||
|
* when they fail, with the programmer there to assess the problem.
|
||||||
|
*
|
||||||
|
* In short: you can sprinkle these around liberally and assume they will
|
||||||
|
* evaporate out of the build when building for end-users.
|
||||||
|
*
|
||||||
|
* When assertions are disabled, this wraps `condition` in a `sizeof`
|
||||||
|
* operator, which means any function calls and side effects will not run, but
|
||||||
|
* the compiler will not complain about any otherwise-unused variables that
|
||||||
|
* are only referenced in the assertion.
|
||||||
|
*
|
||||||
|
* One can set the environment variable "SDL_ASSERT" to one of several strings
|
||||||
|
* ("abort", "break", "retry", "ignore", "always_ignore") to force a default
|
||||||
|
* behavior, which may be desirable for automation purposes. If your platform
|
||||||
|
* requires GUI interfaces to happen on the main thread but you're debugging
|
||||||
|
* an assertion in a background thread, it might be desirable to set this to
|
||||||
|
* "break" so that your debugger takes control as soon as assert is triggered,
|
||||||
|
* instead of risking a bad UI interaction (deadlock, etc) in the application.
|
||||||
|
*
|
||||||
|
* \param condition boolean value to test.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this macro from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_assert(condition) if (assertion_enabled && (condition)) { trigger_assertion; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An assertion test that is performed even in release builds.
|
||||||
|
*
|
||||||
|
* This macro is enabled when the SDL_ASSERT_LEVEL is >= 1, otherwise it is
|
||||||
|
* disabled. This is meant to be for tests that are cheap to make and
|
||||||
|
* extremely unlikely to fail; generally it is frowned upon to have an
|
||||||
|
* assertion failure in a release build, so these assertions generally need to
|
||||||
|
* be of more than life-and-death importance if there's a chance they might
|
||||||
|
* trigger. You should almost always consider handling these cases more
|
||||||
|
* gracefully than an assert allows.
|
||||||
|
*
|
||||||
|
* When assertions are disabled, this wraps `condition` in a `sizeof`
|
||||||
|
* operator, which means any function calls and side effects will not run, but
|
||||||
|
* the compiler will not complain about any otherwise-unused variables that
|
||||||
|
* are only referenced in the assertion.
|
||||||
|
*
|
||||||
|
* One can set the environment variable "SDL_ASSERT" to one of several strings
|
||||||
|
* ("abort", "break", "retry", "ignore", "always_ignore") to force a default
|
||||||
|
* behavior, which may be desirable for automation purposes. If your platform
|
||||||
|
* requires GUI interfaces to happen on the main thread but you're debugging
|
||||||
|
* an assertion in a background thread, it might be desirable to set this to
|
||||||
|
* "break" so that your debugger takes control as soon as assert is triggered,
|
||||||
|
* instead of risking a bad UI interaction (deadlock, etc) in the application.
|
||||||
|
* *
|
||||||
|
*
|
||||||
|
* \param condition boolean value to test.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this macro from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_assert_release(condition) SDL_disabled_assert(condition)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An assertion test that is performed only when built with paranoid settings.
|
||||||
|
*
|
||||||
|
* This macro is enabled when the SDL_ASSERT_LEVEL is >= 3, otherwise it is
|
||||||
|
* disabled. This is a higher level than both release and debug, so these
|
||||||
|
* tests are meant to be expensive and only run when specifically looking for
|
||||||
|
* extremely unexpected failure cases in a special build.
|
||||||
|
*
|
||||||
|
* When assertions are disabled, this wraps `condition` in a `sizeof`
|
||||||
|
* operator, which means any function calls and side effects will not run, but
|
||||||
|
* the compiler will not complain about any otherwise-unused variables that
|
||||||
|
* are only referenced in the assertion.
|
||||||
|
*
|
||||||
|
* One can set the environment variable "SDL_ASSERT" to one of several strings
|
||||||
|
* ("abort", "break", "retry", "ignore", "always_ignore") to force a default
|
||||||
|
* behavior, which may be desirable for automation purposes. If your platform
|
||||||
|
* requires GUI interfaces to happen on the main thread but you're debugging
|
||||||
|
* an assertion in a background thread, it might be desirable to set this to
|
||||||
|
* "break" so that your debugger takes control as soon as assert is triggered,
|
||||||
|
* instead of risking a bad UI interaction (deadlock, etc) in the application.
|
||||||
|
*
|
||||||
|
* \param condition boolean value to test.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this macro from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
|
||||||
|
|
||||||
|
/* Enable various levels of assertions. */
|
||||||
|
#elif SDL_ASSERT_LEVEL == 0 /* assertions disabled */
|
||||||
|
# define SDL_assert(condition) SDL_disabled_assert(condition)
|
||||||
|
# define SDL_assert_release(condition) SDL_disabled_assert(condition)
|
||||||
|
# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
|
||||||
|
#elif SDL_ASSERT_LEVEL == 1 /* release settings. */
|
||||||
|
# define SDL_assert(condition) SDL_disabled_assert(condition)
|
||||||
|
# define SDL_assert_release(condition) SDL_enabled_assert(condition)
|
||||||
|
# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
|
||||||
|
#elif SDL_ASSERT_LEVEL == 2 /* debug settings. */
|
||||||
|
# define SDL_assert(condition) SDL_enabled_assert(condition)
|
||||||
|
# define SDL_assert_release(condition) SDL_enabled_assert(condition)
|
||||||
|
# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
|
||||||
|
#elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */
|
||||||
|
# define SDL_assert(condition) SDL_enabled_assert(condition)
|
||||||
|
# define SDL_assert_release(condition) SDL_enabled_assert(condition)
|
||||||
|
# define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
|
||||||
|
#else
|
||||||
|
# error Unknown assertion level.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An assertion test that is always performed.
|
||||||
|
*
|
||||||
|
* This macro is always enabled no matter what SDL_ASSERT_LEVEL is set to. You
|
||||||
|
* almost never want to use this, as it could trigger on an end-user's system,
|
||||||
|
* crashing your program.
|
||||||
|
*
|
||||||
|
* One can set the environment variable "SDL_ASSERT" to one of several strings
|
||||||
|
* ("abort", "break", "retry", "ignore", "always_ignore") to force a default
|
||||||
|
* behavior, which may be desirable for automation purposes. If your platform
|
||||||
|
* requires GUI interfaces to happen on the main thread but you're debugging
|
||||||
|
* an assertion in a background thread, it might be desirable to set this to
|
||||||
|
* "break" so that your debugger takes control as soon as assert is triggered,
|
||||||
|
* instead of risking a bad UI interaction (deadlock, etc) in the application.
|
||||||
|
*
|
||||||
|
* \param condition boolean value to test.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this macro from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_assert_always(condition) SDL_enabled_assert(condition)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback that fires when an SDL assertion fails.
|
||||||
|
*
|
||||||
|
* \param data a pointer to the SDL_AssertData structure corresponding to the
|
||||||
|
* current assertion.
|
||||||
|
* \param userdata what was passed as `userdata` to SDL_SetAssertionHandler().
|
||||||
|
* \returns an SDL_AssertState value indicating how to handle the failure.
|
||||||
|
*
|
||||||
|
* \threadsafety This callback may be called from any thread that triggers an
|
||||||
|
* assert at any time.
|
||||||
|
*
|
||||||
|
* \since This datatype is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
|
||||||
|
const SDL_AssertData *data, void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an application-defined assertion handler.
|
||||||
|
*
|
||||||
|
* This function allows an application to show its own assertion UI and/or
|
||||||
|
* force the response to an assertion failure. If the application doesn't
|
||||||
|
* provide this, SDL will try to do the right thing, popping up a
|
||||||
|
* system-specific GUI dialog, and probably minimizing any fullscreen windows.
|
||||||
|
*
|
||||||
|
* This callback may fire from any thread, but it runs wrapped in a mutex, so
|
||||||
|
* it will only fire from one thread at a time.
|
||||||
|
*
|
||||||
|
* This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
|
||||||
|
*
|
||||||
|
* \param handler the SDL_AssertionHandler function to call when an assertion
|
||||||
|
* fails or NULL for the default handler.
|
||||||
|
* \param userdata a pointer that is passed to `handler`.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetAssertionHandler
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_SetAssertionHandler(
|
||||||
|
SDL_AssertionHandler handler,
|
||||||
|
void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default assertion handler.
|
||||||
|
*
|
||||||
|
* This returns the function pointer that is called by default when an
|
||||||
|
* assertion is triggered. This is an internal function provided by SDL, that
|
||||||
|
* is used for assertions when SDL_SetAssertionHandler() hasn't been used to
|
||||||
|
* provide a different function.
|
||||||
|
*
|
||||||
|
* \returns the default SDL_AssertionHandler that is called when an assert
|
||||||
|
* triggers.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetAssertionHandler
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current assertion handler.
|
||||||
|
*
|
||||||
|
* This returns the function pointer that is called when an assertion is
|
||||||
|
* triggered. This is either the value last passed to
|
||||||
|
* SDL_SetAssertionHandler(), or if no application-specified function is set,
|
||||||
|
* is equivalent to calling SDL_GetDefaultAssertionHandler().
|
||||||
|
*
|
||||||
|
* The parameter `puserdata` is a pointer to a void*, which will store the
|
||||||
|
* "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value
|
||||||
|
* will always be NULL for the default handler. If you don't care about this
|
||||||
|
* data, it is safe to pass a NULL pointer to this function to ignore it.
|
||||||
|
*
|
||||||
|
* \param puserdata pointer which is filled with the "userdata" pointer that
|
||||||
|
* was passed to SDL_SetAssertionHandler().
|
||||||
|
* \returns the SDL_AssertionHandler that is called when an assert triggers.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_SetAssertionHandler
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of all assertion failures.
|
||||||
|
*
|
||||||
|
* This function gets all assertions triggered since the last call to
|
||||||
|
* SDL_ResetAssertionReport(), or the start of the program.
|
||||||
|
*
|
||||||
|
* The proper way to examine this data looks something like this:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* const SDL_AssertData *item = SDL_GetAssertionReport();
|
||||||
|
* while (item) {
|
||||||
|
* printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n",
|
||||||
|
* item->condition, item->function, item->filename,
|
||||||
|
* item->linenum, item->trigger_count,
|
||||||
|
* item->always_ignore ? "yes" : "no");
|
||||||
|
* item = item->next;
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* \returns a list of all failed assertions or NULL if the list is empty. This
|
||||||
|
* memory should not be modified or freed by the application. This
|
||||||
|
* pointer remains valid until the next call to SDL_Quit() or
|
||||||
|
* SDL_ResetAssertionReport().
|
||||||
|
*
|
||||||
|
* \threadsafety This function is not thread safe. Other threads calling
|
||||||
|
* SDL_ResetAssertionReport() simultaneously, may render the
|
||||||
|
* returned pointer invalid.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_ResetAssertionReport
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the list of all assertion failures.
|
||||||
|
*
|
||||||
|
* This function will clear the list of all assertions triggered up to that
|
||||||
|
* point. Immediately following this call, SDL_GetAssertionReport will return
|
||||||
|
* no items. In addition, any previously-triggered assertions will be reset to
|
||||||
|
* a trigger_count of zero, and their always_ignore state will be false.
|
||||||
|
*
|
||||||
|
* \threadsafety This function is not thread safe. Other threads triggering an
|
||||||
|
* assertion, or simultaneously calling this function may cause
|
||||||
|
* memory leaks or crashes.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetAssertionReport
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <SDL3/SDL_close_code.h>
|
||||||
|
|
||||||
|
#endif /* SDL_assert_h_ */
|
||||||
@@ -0,0 +1,546 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WIKI CATEGORY: AsyncIO */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # CategoryAsyncIO
|
||||||
|
*
|
||||||
|
* SDL offers a way to perform I/O asynchronously. This allows an app to read
|
||||||
|
* or write files without waiting for data to actually transfer; the functions
|
||||||
|
* that request I/O never block while the request is fulfilled.
|
||||||
|
*
|
||||||
|
* Instead, the data moves in the background and the app can check for results
|
||||||
|
* at their leisure.
|
||||||
|
*
|
||||||
|
* This is more complicated than just reading and writing files in a
|
||||||
|
* synchronous way, but it can allow for more efficiency, and never having
|
||||||
|
* framerate drops as the hard drive catches up, etc.
|
||||||
|
*
|
||||||
|
* The general usage pattern for async I/O is:
|
||||||
|
*
|
||||||
|
* - Create one or more SDL_AsyncIOQueue objects.
|
||||||
|
* - Open files with SDL_AsyncIOFromFile.
|
||||||
|
* - Start I/O tasks to the files with SDL_ReadAsyncIO or SDL_WriteAsyncIO,
|
||||||
|
* putting those tasks into one of the queues.
|
||||||
|
* - Later on, use SDL_GetAsyncIOResult on a queue to see if any task is
|
||||||
|
* finished without blocking. Tasks might finish in any order with success
|
||||||
|
* or failure.
|
||||||
|
* - When all your tasks are done, close the file with SDL_CloseAsyncIO. This
|
||||||
|
* also generates a task, since it might flush data to disk!
|
||||||
|
*
|
||||||
|
* This all works, without blocking, in a single thread, but one can also wait
|
||||||
|
* on a queue in a background thread, sleeping until new results have arrived:
|
||||||
|
*
|
||||||
|
* - Call SDL_WaitAsyncIOResult from one or more threads to efficiently block
|
||||||
|
* until new tasks complete.
|
||||||
|
* - When shutting down, call SDL_SignalAsyncIOQueue to unblock any sleeping
|
||||||
|
* threads despite there being no new tasks completed.
|
||||||
|
*
|
||||||
|
* And, of course, to match the synchronous SDL_LoadFile, we offer
|
||||||
|
* SDL_LoadFileAsync as a convenience function. This will handle allocating a
|
||||||
|
* buffer, slurping in the file data, and null-terminating it; you still check
|
||||||
|
* for results later.
|
||||||
|
*
|
||||||
|
* Behind the scenes, SDL will use newer, efficient APIs on platforms that
|
||||||
|
* support them: Linux's io_uring and Windows 11's IoRing, for example. If
|
||||||
|
* those technologies aren't available, SDL will offload the work to a thread
|
||||||
|
* pool that will manage otherwise-synchronous loads without blocking the app.
|
||||||
|
*
|
||||||
|
* ## Best Practices
|
||||||
|
*
|
||||||
|
* Simple non-blocking I/O--for an app that just wants to pick up data
|
||||||
|
* whenever it's ready without losing framerate waiting on disks to spin--can
|
||||||
|
* use whatever pattern works well for the program. In this case, simply call
|
||||||
|
* SDL_ReadAsyncIO, or maybe SDL_LoadFileAsync, as needed. Once a frame, call
|
||||||
|
* SDL_GetAsyncIOResult to check for any completed tasks and deal with the
|
||||||
|
* data as it arrives.
|
||||||
|
*
|
||||||
|
* If two separate pieces of the same program need their own I/O, it is legal
|
||||||
|
* for each to create their own queue. This will prevent either piece from
|
||||||
|
* accidentally consuming the other's completed tasks. Each queue does require
|
||||||
|
* some amount of resources, but it is not an overwhelming cost. Do not make a
|
||||||
|
* queue for each task, however. It is better to put many tasks into a single
|
||||||
|
* queue. They will be reported in order of completion, not in the order they
|
||||||
|
* were submitted, so it doesn't generally matter what order tasks are
|
||||||
|
* started.
|
||||||
|
*
|
||||||
|
* One async I/O queue can be shared by multiple threads, or one thread can
|
||||||
|
* have more than one queue, but the most efficient way--if ruthless
|
||||||
|
* efficiency is the goal--is to have one queue per thread, with multiple
|
||||||
|
* threads working in parallel, and attempt to keep each queue loaded with
|
||||||
|
* tasks that are both started by and consumed by the same thread. On modern
|
||||||
|
* platforms that can use newer interfaces, this can keep data flowing as
|
||||||
|
* efficiently as possible all the way from storage hardware to the app, with
|
||||||
|
* no contention between threads for access to the same queue.
|
||||||
|
*
|
||||||
|
* Written data is not guaranteed to make it to physical media by the time a
|
||||||
|
* closing task is completed, unless SDL_CloseAsyncIO is called with its
|
||||||
|
* `flush` parameter set to true, which is to say that a successful result
|
||||||
|
* here can still result in lost data during an unfortunately-timed power
|
||||||
|
* outage if not flushed. However, flushing will take longer and may be
|
||||||
|
* unnecessary, depending on the app's needs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_asyncio_h_
|
||||||
|
#define SDL_asyncio_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The asynchronous I/O operation structure.
|
||||||
|
*
|
||||||
|
* This operates as an opaque handle. One can then request read or write
|
||||||
|
* operations on it.
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_AsyncIOFromFile
|
||||||
|
*/
|
||||||
|
typedef struct SDL_AsyncIO SDL_AsyncIO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of asynchronous I/O tasks.
|
||||||
|
*
|
||||||
|
* \since This enum is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef enum SDL_AsyncIOTaskType
|
||||||
|
{
|
||||||
|
SDL_ASYNCIO_TASK_READ, /**< A read operation. */
|
||||||
|
SDL_ASYNCIO_TASK_WRITE, /**< A write operation. */
|
||||||
|
SDL_ASYNCIO_TASK_CLOSE /**< A close operation. */
|
||||||
|
} SDL_AsyncIOTaskType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible outcomes of an asynchronous I/O task.
|
||||||
|
*
|
||||||
|
* \since This enum is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef enum SDL_AsyncIOResult
|
||||||
|
{
|
||||||
|
SDL_ASYNCIO_COMPLETE, /**< request was completed without error */
|
||||||
|
SDL_ASYNCIO_FAILURE, /**< request failed for some reason; check SDL_GetError()! */
|
||||||
|
SDL_ASYNCIO_CANCELED /**< request was canceled before completing. */
|
||||||
|
} SDL_AsyncIOResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about a completed asynchronous I/O request.
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef struct SDL_AsyncIOOutcome
|
||||||
|
{
|
||||||
|
SDL_AsyncIO *asyncio; /**< what generated this task. This pointer will be invalid if it was closed! */
|
||||||
|
SDL_AsyncIOTaskType type; /**< What sort of task was this? Read, write, etc? */
|
||||||
|
SDL_AsyncIOResult result; /**< the result of the work (success, failure, cancellation). */
|
||||||
|
void *buffer; /**< buffer where data was read/written. */
|
||||||
|
Uint64 offset; /**< offset in the SDL_AsyncIO where data was read/written. */
|
||||||
|
Uint64 bytes_requested; /**< number of bytes the task was to read/write. */
|
||||||
|
Uint64 bytes_transferred; /**< actual number of bytes that were read/written. */
|
||||||
|
void *userdata; /**< pointer provided by the app when starting the task */
|
||||||
|
} SDL_AsyncIOOutcome;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A queue of completed asynchronous I/O tasks.
|
||||||
|
*
|
||||||
|
* When starting an asynchronous operation, you specify a queue for the new
|
||||||
|
* task. A queue can be asked later if any tasks in it have completed,
|
||||||
|
* allowing an app to manage multiple pending tasks in one place, in whatever
|
||||||
|
* order they complete.
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_CreateAsyncIOQueue
|
||||||
|
* \sa SDL_ReadAsyncIO
|
||||||
|
* \sa SDL_WriteAsyncIO
|
||||||
|
* \sa SDL_GetAsyncIOResult
|
||||||
|
* \sa SDL_WaitAsyncIOResult
|
||||||
|
*/
|
||||||
|
typedef struct SDL_AsyncIOQueue SDL_AsyncIOQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to create a new SDL_AsyncIO object for reading from
|
||||||
|
* and/or writing to a named file.
|
||||||
|
*
|
||||||
|
* The `mode` string understands the following values:
|
||||||
|
*
|
||||||
|
* - "r": Open a file for reading only. It must exist.
|
||||||
|
* - "w": Open a file for writing only. It will create missing files or
|
||||||
|
* truncate existing ones.
|
||||||
|
* - "r+": Open a file for update both reading and writing. The file must
|
||||||
|
* exist.
|
||||||
|
* - "w+": Create an empty file for both reading and writing. If a file with
|
||||||
|
* the same name already exists its content is erased and the file is
|
||||||
|
* treated as a new empty file.
|
||||||
|
*
|
||||||
|
* There is no "b" mode, as there is only "binary" style I/O, and no "a" mode
|
||||||
|
* for appending, since you specify the position when starting a task.
|
||||||
|
*
|
||||||
|
* This function supports Unicode filenames, but they must be encoded in UTF-8
|
||||||
|
* format, regardless of the underlying operating system.
|
||||||
|
*
|
||||||
|
* This call is _not_ asynchronous; it will open the file before returning,
|
||||||
|
* under the assumption that doing so is generally a fast operation. Future
|
||||||
|
* reads and writes to the opened file will be async, however.
|
||||||
|
*
|
||||||
|
* \param file a UTF-8 string representing the filename to open.
|
||||||
|
* \param mode an ASCII string representing the mode to be used for opening
|
||||||
|
* the file.
|
||||||
|
* \returns a pointer to the SDL_AsyncIO structure that is created or NULL on
|
||||||
|
* failure; call SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_CloseAsyncIO
|
||||||
|
* \sa SDL_ReadAsyncIO
|
||||||
|
* \sa SDL_WriteAsyncIO
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_AsyncIO * SDLCALL SDL_AsyncIOFromFile(const char *file, const char *mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to get the size of the data stream in an SDL_AsyncIO.
|
||||||
|
*
|
||||||
|
* This call is _not_ asynchronous; it assumes that obtaining this info is a
|
||||||
|
* non-blocking operation in most reasonable cases.
|
||||||
|
*
|
||||||
|
* \param asyncio the SDL_AsyncIO to get the size of the data stream from.
|
||||||
|
* \returns the size of the data stream in the SDL_IOStream on success or a
|
||||||
|
* negative error code on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC Sint64 SDLCALL SDL_GetAsyncIOSize(SDL_AsyncIO *asyncio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start an async read.
|
||||||
|
*
|
||||||
|
* This function reads up to `size` bytes from `offset` position in the data
|
||||||
|
* source to the area pointed at by `ptr`. This function may read less bytes
|
||||||
|
* than requested.
|
||||||
|
*
|
||||||
|
* This function returns as quickly as possible; it does not wait for the read
|
||||||
|
* to complete. On a successful return, this work will continue in the
|
||||||
|
* background. If the work begins, even failure is asynchronous: a failing
|
||||||
|
* return value from this function only means the work couldn't start at all.
|
||||||
|
*
|
||||||
|
* `ptr` must remain available until the work is done, and may be accessed by
|
||||||
|
* the system at any time until then. Do not allocate it on the stack, as this
|
||||||
|
* might take longer than the life of the calling function to complete!
|
||||||
|
*
|
||||||
|
* An SDL_AsyncIOQueue must be specified. The newly-created task will be added
|
||||||
|
* to it when it completes its work.
|
||||||
|
*
|
||||||
|
* \param asyncio a pointer to an SDL_AsyncIO structure.
|
||||||
|
* \param ptr a pointer to a buffer to read data into.
|
||||||
|
* \param offset the position to start reading in the data source.
|
||||||
|
* \param size the number of bytes to read from the data source.
|
||||||
|
* \param queue a queue to add the new SDL_AsyncIO to.
|
||||||
|
* \param userdata an app-defined pointer that will be provided with the task
|
||||||
|
* results.
|
||||||
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_WriteAsyncIO
|
||||||
|
* \sa SDL_CreateAsyncIOQueue
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_ReadAsyncIO(SDL_AsyncIO *asyncio, void *ptr, Uint64 offset, Uint64 size, SDL_AsyncIOQueue *queue, void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start an async write.
|
||||||
|
*
|
||||||
|
* This function writes `size` bytes from `offset` position in the data source
|
||||||
|
* to the area pointed at by `ptr`.
|
||||||
|
*
|
||||||
|
* This function returns as quickly as possible; it does not wait for the
|
||||||
|
* write to complete. On a successful return, this work will continue in the
|
||||||
|
* background. If the work begins, even failure is asynchronous: a failing
|
||||||
|
* return value from this function only means the work couldn't start at all.
|
||||||
|
*
|
||||||
|
* `ptr` must remain available until the work is done, and may be accessed by
|
||||||
|
* the system at any time until then. Do not allocate it on the stack, as this
|
||||||
|
* might take longer than the life of the calling function to complete!
|
||||||
|
*
|
||||||
|
* An SDL_AsyncIOQueue must be specified. The newly-created task will be added
|
||||||
|
* to it when it completes its work.
|
||||||
|
*
|
||||||
|
* \param asyncio a pointer to an SDL_AsyncIO structure.
|
||||||
|
* \param ptr a pointer to a buffer to write data from.
|
||||||
|
* \param offset the position to start writing to the data source.
|
||||||
|
* \param size the number of bytes to write to the data source.
|
||||||
|
* \param queue a queue to add the new SDL_AsyncIO to.
|
||||||
|
* \param userdata an app-defined pointer that will be provided with the task
|
||||||
|
* results.
|
||||||
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_ReadAsyncIO
|
||||||
|
* \sa SDL_CreateAsyncIOQueue
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_WriteAsyncIO(SDL_AsyncIO *asyncio, void *ptr, Uint64 offset, Uint64 size, SDL_AsyncIOQueue *queue, void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close and free any allocated resources for an async I/O object.
|
||||||
|
*
|
||||||
|
* Closing a file is _also_ an asynchronous task! If a write failure were to
|
||||||
|
* happen during the closing process, for example, the task results will
|
||||||
|
* report it as usual.
|
||||||
|
*
|
||||||
|
* Closing a file that has been written to does not guarantee the data has
|
||||||
|
* made it to physical media; it may remain in the operating system's file
|
||||||
|
* cache, for later writing to disk. This means that a successfully-closed
|
||||||
|
* file can be lost if the system crashes or loses power in this small window.
|
||||||
|
* To prevent this, call this function with the `flush` parameter set to true.
|
||||||
|
* This will make the operation take longer, and perhaps increase system load
|
||||||
|
* in general, but a successful result guarantees that the data has made it to
|
||||||
|
* physical storage. Don't use this for temporary files, caches, and
|
||||||
|
* unimportant data, and definitely use it for crucial irreplaceable files,
|
||||||
|
* like game saves.
|
||||||
|
*
|
||||||
|
* This function guarantees that the close will happen after any other pending
|
||||||
|
* tasks to `asyncio`, so it's safe to open a file, start several operations,
|
||||||
|
* close the file immediately, then check for all results later. This function
|
||||||
|
* will not block until the tasks have completed.
|
||||||
|
*
|
||||||
|
* Once this function returns true, `asyncio` is no longer valid, regardless
|
||||||
|
* of any future outcomes. Any completed tasks might still contain this
|
||||||
|
* pointer in their SDL_AsyncIOOutcome data, in case the app was using this
|
||||||
|
* value to track information, but it should not be used again.
|
||||||
|
*
|
||||||
|
* If this function returns false, the close wasn't started at all, and it's
|
||||||
|
* safe to attempt to close again later.
|
||||||
|
*
|
||||||
|
* An SDL_AsyncIOQueue must be specified. The newly-created task will be added
|
||||||
|
* to it when it completes its work.
|
||||||
|
*
|
||||||
|
* \param asyncio a pointer to an SDL_AsyncIO structure to close.
|
||||||
|
* \param flush true if data should sync to disk before the task completes.
|
||||||
|
* \param queue a queue to add the new SDL_AsyncIO to.
|
||||||
|
* \param userdata an app-defined pointer that will be provided with the task
|
||||||
|
* results.
|
||||||
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread, but two
|
||||||
|
* threads should not attempt to close the same object.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_CloseAsyncIO(SDL_AsyncIO *asyncio, bool flush, SDL_AsyncIOQueue *queue, void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a task queue for tracking multiple I/O operations.
|
||||||
|
*
|
||||||
|
* Async I/O operations are assigned to a queue when started. The queue can be
|
||||||
|
* checked for completed tasks thereafter.
|
||||||
|
*
|
||||||
|
* \returns a new task queue object or NULL if there was an error; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_DestroyAsyncIOQueue
|
||||||
|
* \sa SDL_GetAsyncIOResult
|
||||||
|
* \sa SDL_WaitAsyncIOResult
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_AsyncIOQueue * SDLCALL SDL_CreateAsyncIOQueue(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a previously-created async I/O task queue.
|
||||||
|
*
|
||||||
|
* If there are still tasks pending for this queue, this call will block until
|
||||||
|
* those tasks are finished. All those tasks will be deallocated. Their
|
||||||
|
* results will be lost to the app.
|
||||||
|
*
|
||||||
|
* Any pending reads from SDL_LoadFileAsync() that are still in this queue
|
||||||
|
* will have their buffers deallocated by this function, to prevent a memory
|
||||||
|
* leak.
|
||||||
|
*
|
||||||
|
* Once this function is called, the queue is no longer valid and should not
|
||||||
|
* be used, including by other threads that might access it while destruction
|
||||||
|
* is blocking on pending tasks.
|
||||||
|
*
|
||||||
|
* Do not destroy a queue that still has threads waiting on it through
|
||||||
|
* SDL_WaitAsyncIOResult(). You can call SDL_SignalAsyncIOQueue() first to
|
||||||
|
* unblock those threads, and take measures (such as SDL_WaitThread()) to make
|
||||||
|
* sure they have finished their wait and won't wait on the queue again.
|
||||||
|
*
|
||||||
|
* \param queue the task queue to destroy.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread, so long as
|
||||||
|
* no other thread is waiting on the queue with
|
||||||
|
* SDL_WaitAsyncIOResult.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_DestroyAsyncIOQueue(SDL_AsyncIOQueue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query an async I/O task queue for completed tasks.
|
||||||
|
*
|
||||||
|
* If a task assigned to this queue has finished, this will return true and
|
||||||
|
* fill in `outcome` with the details of the task. If no task in the queue has
|
||||||
|
* finished, this function will return false. This function does not block.
|
||||||
|
*
|
||||||
|
* If a task has completed, this function will free its resources and the task
|
||||||
|
* pointer will no longer be valid. The task will be removed from the queue.
|
||||||
|
*
|
||||||
|
* It is safe for multiple threads to call this function on the same queue at
|
||||||
|
* once; a completed task will only go to one of the threads.
|
||||||
|
*
|
||||||
|
* \param queue the async I/O task queue to query.
|
||||||
|
* \param outcome details of a finished task will be written here. May not be
|
||||||
|
* NULL.
|
||||||
|
* \returns true if a task has completed, false otherwise.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_WaitAsyncIOResult
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_GetAsyncIOResult(SDL_AsyncIOQueue *queue, SDL_AsyncIOOutcome *outcome);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Block until an async I/O task queue has a completed task.
|
||||||
|
*
|
||||||
|
* This function puts the calling thread to sleep until there a task assigned
|
||||||
|
* to the queue that has finished.
|
||||||
|
*
|
||||||
|
* If a task assigned to the queue has finished, this will return true and
|
||||||
|
* fill in `outcome` with the details of the task. If no task in the queue has
|
||||||
|
* finished, this function will return false.
|
||||||
|
*
|
||||||
|
* If a task has completed, this function will free its resources and the task
|
||||||
|
* pointer will no longer be valid. The task will be removed from the queue.
|
||||||
|
*
|
||||||
|
* It is safe for multiple threads to call this function on the same queue at
|
||||||
|
* once; a completed task will only go to one of the threads.
|
||||||
|
*
|
||||||
|
* Note that by the nature of various platforms, more than one waiting thread
|
||||||
|
* may wake to handle a single task, but only one will obtain it, so
|
||||||
|
* `timeoutMS` is a _maximum_ wait time, and this function may return false
|
||||||
|
* sooner.
|
||||||
|
*
|
||||||
|
* This function may return false if there was a system error, the OS
|
||||||
|
* inadvertently awoke multiple threads, or if SDL_SignalAsyncIOQueue() was
|
||||||
|
* called to wake up all waiting threads without a finished task.
|
||||||
|
*
|
||||||
|
* A timeout can be used to specify a maximum wait time, but rather than
|
||||||
|
* polling, it is possible to have a timeout of -1 to wait forever, and use
|
||||||
|
* SDL_SignalAsyncIOQueue() to wake up the waiting threads later.
|
||||||
|
*
|
||||||
|
* \param queue the async I/O task queue to wait on.
|
||||||
|
* \param outcome details of a finished task will be written here. May not be
|
||||||
|
* NULL.
|
||||||
|
* \param timeoutMS the maximum time to wait, in milliseconds, or -1 to wait
|
||||||
|
* indefinitely.
|
||||||
|
* \returns true if task has completed, false otherwise.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_SignalAsyncIOQueue
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_WaitAsyncIOResult(SDL_AsyncIOQueue *queue, SDL_AsyncIOOutcome *outcome, Sint32 timeoutMS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wake up any threads that are blocking in SDL_WaitAsyncIOResult().
|
||||||
|
*
|
||||||
|
* This will unblock any threads that are sleeping in a call to
|
||||||
|
* SDL_WaitAsyncIOResult for the specified queue, and cause them to return
|
||||||
|
* from that function.
|
||||||
|
*
|
||||||
|
* This can be useful when destroying a queue to make sure nothing is touching
|
||||||
|
* it indefinitely. In this case, once this call completes, the caller should
|
||||||
|
* take measures to make sure any previously-blocked threads have returned
|
||||||
|
* from their wait and will not touch the queue again (perhaps by setting a
|
||||||
|
* flag to tell the threads to terminate and then using SDL_WaitThread() to
|
||||||
|
* make sure they've done so).
|
||||||
|
*
|
||||||
|
* \param queue the async I/O task queue to signal.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_WaitAsyncIOResult
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_SignalAsyncIOQueue(SDL_AsyncIOQueue *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all the data from a file path, asynchronously.
|
||||||
|
*
|
||||||
|
* This function returns as quickly as possible; it does not wait for the read
|
||||||
|
* to complete. On a successful return, this work will continue in the
|
||||||
|
* background. If the work begins, even failure is asynchronous: a failing
|
||||||
|
* return value from this function only means the work couldn't start at all.
|
||||||
|
*
|
||||||
|
* The data is allocated with a zero byte at the end (null terminated) for
|
||||||
|
* convenience. This extra byte is not included in SDL_AsyncIOOutcome's
|
||||||
|
* bytes_transferred value.
|
||||||
|
*
|
||||||
|
* This function will allocate the buffer to contain the file. It must be
|
||||||
|
* deallocated by calling SDL_free() on SDL_AsyncIOOutcome's buffer field
|
||||||
|
* after completion.
|
||||||
|
*
|
||||||
|
* An SDL_AsyncIOQueue must be specified. The newly-created task will be added
|
||||||
|
* to it when it completes its work.
|
||||||
|
*
|
||||||
|
* \param file the path to read all available data from.
|
||||||
|
* \param queue a queue to add the new SDL_AsyncIO to.
|
||||||
|
* \param userdata an app-defined pointer that will be provided with the task
|
||||||
|
* results.
|
||||||
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_LoadFile_IO
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_LoadFileAsync(const char *file, SDL_AsyncIOQueue *queue, void *userdata);
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <SDL3/SDL_close_code.h>
|
||||||
|
|
||||||
|
#endif /* SDL_asyncio_h_ */
|
||||||
@@ -0,0 +1,664 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # CategoryAtomic
|
||||||
|
*
|
||||||
|
* Atomic operations.
|
||||||
|
*
|
||||||
|
* IMPORTANT: If you are not an expert in concurrent lockless programming, you
|
||||||
|
* should not be using any functions in this file. You should be protecting
|
||||||
|
* your data structures with full mutexes instead.
|
||||||
|
*
|
||||||
|
* ***Seriously, here be dragons!***
|
||||||
|
*
|
||||||
|
* You can find out a little more about lockless programming and the subtle
|
||||||
|
* issues that can arise here:
|
||||||
|
* https://learn.microsoft.com/en-us/windows/win32/dxtecharts/lockless-programming
|
||||||
|
*
|
||||||
|
* There's also lots of good information here:
|
||||||
|
*
|
||||||
|
* - https://www.1024cores.net/home/lock-free-algorithms
|
||||||
|
* - https://preshing.com/
|
||||||
|
*
|
||||||
|
* These operations may or may not actually be implemented using processor
|
||||||
|
* specific atomic operations. When possible they are implemented as true
|
||||||
|
* processor specific atomic operations. When that is not possible the are
|
||||||
|
* implemented using locks that *do* use the available atomic operations.
|
||||||
|
*
|
||||||
|
* All of the atomic operations that modify memory are full memory barriers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_atomic_h_
|
||||||
|
#define SDL_atomic_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
#include <SDL3/SDL_platform_defines.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An atomic spinlock.
|
||||||
|
*
|
||||||
|
* The atomic locks are efficient spinlocks using CPU instructions, but are
|
||||||
|
* vulnerable to starvation and can spin forever if a thread holding a lock
|
||||||
|
* has been terminated. For this reason you should minimize the code executed
|
||||||
|
* inside an atomic lock and never do expensive things like API or system
|
||||||
|
* calls while holding them.
|
||||||
|
*
|
||||||
|
* They are also vulnerable to starvation if the thread holding the lock is
|
||||||
|
* lower priority than other threads and doesn't get scheduled. In general you
|
||||||
|
* should use mutexes instead, since they have better performance and
|
||||||
|
* contention behavior.
|
||||||
|
*
|
||||||
|
* The atomic locks are not safe to lock recursively.
|
||||||
|
*
|
||||||
|
* Porting Note: The spin lock functions and type are required and can not be
|
||||||
|
* emulated because they are used in the atomic emulation code.
|
||||||
|
*/
|
||||||
|
typedef int SDL_SpinLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to lock a spin lock by setting it to a non-zero value.
|
||||||
|
*
|
||||||
|
* ***Please note that spinlocks are dangerous if you don't know what you're
|
||||||
|
* doing. Please be careful using any sort of spinlock!***
|
||||||
|
*
|
||||||
|
* \param lock a pointer to a lock variable.
|
||||||
|
* \returns true if the lock succeeded, false if the lock is already held.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_LockSpinlock
|
||||||
|
* \sa SDL_UnlockSpinlock
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_TryLockSpinlock(SDL_SpinLock *lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock a spin lock by setting it to a non-zero value.
|
||||||
|
*
|
||||||
|
* ***Please note that spinlocks are dangerous if you don't know what you're
|
||||||
|
* doing. Please be careful using any sort of spinlock!***
|
||||||
|
*
|
||||||
|
* \param lock a pointer to a lock variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_TryLockSpinlock
|
||||||
|
* \sa SDL_UnlockSpinlock
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_LockSpinlock(SDL_SpinLock *lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock a spin lock by setting it to 0.
|
||||||
|
*
|
||||||
|
* Always returns immediately.
|
||||||
|
*
|
||||||
|
* ***Please note that spinlocks are dangerous if you don't know what you're
|
||||||
|
* doing. Please be careful using any sort of spinlock!***
|
||||||
|
*
|
||||||
|
* \param lock a pointer to a lock variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_LockSpinlock
|
||||||
|
* \sa SDL_TryLockSpinlock
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_UnlockSpinlock(SDL_SpinLock *lock);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a compiler barrier.
|
||||||
|
*
|
||||||
|
* A compiler barrier prevents the compiler from reordering reads and writes
|
||||||
|
* to globally visible variables across the call.
|
||||||
|
*
|
||||||
|
* This macro only prevents the compiler from reordering reads and writes, it
|
||||||
|
* does not prevent the CPU from reordering reads and writes. However, all of
|
||||||
|
* the atomic operations that modify memory are full memory barriers.
|
||||||
|
*
|
||||||
|
* \threadsafety Obviously this macro is safe to use from any thread at any
|
||||||
|
* time, but if you find yourself needing this, you are probably
|
||||||
|
* dealing with some very sensitive code; be careful!
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_CompilerBarrier() DoCompilerSpecificReadWriteBarrier()
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER) && (_MSC_VER > 1200) && !defined(__clang__)
|
||||||
|
void _ReadWriteBarrier(void);
|
||||||
|
#pragma intrinsic(_ReadWriteBarrier)
|
||||||
|
#define SDL_CompilerBarrier() _ReadWriteBarrier()
|
||||||
|
#elif (defined(__GNUC__) && !defined(SDL_PLATFORM_EMSCRIPTEN)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
|
||||||
|
/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
|
||||||
|
#define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
|
||||||
|
#elif defined(__WATCOMC__)
|
||||||
|
extern __inline void SDL_CompilerBarrier(void);
|
||||||
|
#pragma aux SDL_CompilerBarrier = "" parm [] modify exact [];
|
||||||
|
#else
|
||||||
|
#define SDL_CompilerBarrier() \
|
||||||
|
{ SDL_SpinLock _tmp = 0; SDL_LockSpinlock(&_tmp); SDL_UnlockSpinlock(&_tmp); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a memory release barrier (function version).
|
||||||
|
*
|
||||||
|
* Please refer to SDL_MemoryBarrierRelease for details. This is a function
|
||||||
|
* version, which might be useful if you need to use this functionality from a
|
||||||
|
* scripting language, etc. Also, some of the macro versions call this
|
||||||
|
* function behind the scenes, where more heavy lifting can happen inside of
|
||||||
|
* SDL. Generally, though, an app written in C/C++/etc should use the macro
|
||||||
|
* version, as it will be more efficient.
|
||||||
|
*
|
||||||
|
* \threadsafety Obviously this function is safe to use from any thread at any
|
||||||
|
* time, but if you find yourself needing this, you are probably
|
||||||
|
* dealing with some very sensitive code; be careful!
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_MemoryBarrierRelease
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_MemoryBarrierReleaseFunction(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a memory acquire barrier (function version).
|
||||||
|
*
|
||||||
|
* Please refer to SDL_MemoryBarrierRelease for details. This is a function
|
||||||
|
* version, which might be useful if you need to use this functionality from a
|
||||||
|
* scripting language, etc. Also, some of the macro versions call this
|
||||||
|
* function behind the scenes, where more heavy lifting can happen inside of
|
||||||
|
* SDL. Generally, though, an app written in C/C++/etc should use the macro
|
||||||
|
* version, as it will be more efficient.
|
||||||
|
*
|
||||||
|
* \threadsafety Obviously this function is safe to use from any thread at any
|
||||||
|
* time, but if you find yourself needing this, you are probably
|
||||||
|
* dealing with some very sensitive code; be careful!
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_MemoryBarrierAcquire
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a memory release barrier (macro version).
|
||||||
|
*
|
||||||
|
* Memory barriers are designed to prevent reads and writes from being
|
||||||
|
* reordered by the compiler and being seen out of order on multi-core CPUs.
|
||||||
|
*
|
||||||
|
* A typical pattern would be for thread A to write some data and a flag, and
|
||||||
|
* for thread B to read the flag and get the data. In this case you would
|
||||||
|
* insert a release barrier between writing the data and the flag,
|
||||||
|
* guaranteeing that the data write completes no later than the flag is
|
||||||
|
* written, and you would insert an acquire barrier between reading the flag
|
||||||
|
* and reading the data, to ensure that all the reads associated with the flag
|
||||||
|
* have completed.
|
||||||
|
*
|
||||||
|
* In this pattern you should always see a release barrier paired with an
|
||||||
|
* acquire barrier and you should gate the data reads/writes with a single
|
||||||
|
* flag variable.
|
||||||
|
*
|
||||||
|
* For more information on these semantics, take a look at the blog post:
|
||||||
|
* http://preshing.com/20120913/acquire-and-release-semantics
|
||||||
|
*
|
||||||
|
* This is the macro version of this functionality; if possible, SDL will use
|
||||||
|
* compiler intrinsics or inline assembly, but some platforms might need to
|
||||||
|
* call the function version of this, SDL_MemoryBarrierReleaseFunction to do
|
||||||
|
* the heavy lifting. Apps that can use the macro should favor it over the
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* \threadsafety Obviously this macro is safe to use from any thread at any
|
||||||
|
* time, but if you find yourself needing this, you are probably
|
||||||
|
* dealing with some very sensitive code; be careful!
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_MemoryBarrierAcquire
|
||||||
|
* \sa SDL_MemoryBarrierReleaseFunction
|
||||||
|
*/
|
||||||
|
#define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a memory acquire barrier (macro version).
|
||||||
|
*
|
||||||
|
* Please see SDL_MemoryBarrierRelease for the details on what memory barriers
|
||||||
|
* are and when to use them.
|
||||||
|
*
|
||||||
|
* This is the macro version of this functionality; if possible, SDL will use
|
||||||
|
* compiler intrinsics or inline assembly, but some platforms might need to
|
||||||
|
* call the function version of this, SDL_MemoryBarrierAcquireFunction, to do
|
||||||
|
* the heavy lifting. Apps that can use the macro should favor it over the
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* \threadsafety Obviously this macro is safe to use from any thread at any
|
||||||
|
* time, but if you find yourself needing this, you are probably
|
||||||
|
* dealing with some very sensitive code; be careful!
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_MemoryBarrierRelease
|
||||||
|
* \sa SDL_MemoryBarrierAcquireFunction
|
||||||
|
*/
|
||||||
|
#define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction()
|
||||||
|
|
||||||
|
#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
|
||||||
|
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory")
|
||||||
|
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory")
|
||||||
|
#elif defined(__GNUC__) && defined(__aarch64__)
|
||||||
|
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||||
|
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||||
|
#elif defined(__GNUC__) && defined(__arm__)
|
||||||
|
#if 0 /* defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID) */
|
||||||
|
/* Information from:
|
||||||
|
https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19
|
||||||
|
|
||||||
|
The Linux kernel provides a helper function which provides the right code for a memory barrier,
|
||||||
|
hard-coded at address 0xffff0fa0
|
||||||
|
*/
|
||||||
|
typedef void (*SDL_KernelMemoryBarrierFunc)();
|
||||||
|
#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
|
||||||
|
#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
|
||||||
|
#else
|
||||||
|
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__)
|
||||||
|
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||||
|
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
|
||||||
|
#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
|
||||||
|
#ifdef __thumb__
|
||||||
|
/* The mcr instruction isn't available in thumb mode, use real functions */
|
||||||
|
#define SDL_MEMORY_BARRIER_USES_FUNCTION
|
||||||
|
#define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction()
|
||||||
|
#define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction()
|
||||||
|
#else
|
||||||
|
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
|
||||||
|
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
|
||||||
|
#endif /* __thumb__ */
|
||||||
|
#else
|
||||||
|
#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory")
|
||||||
|
#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory")
|
||||||
|
#endif /* SDL_PLATFORM_LINUX || SDL_PLATFORM_ANDROID */
|
||||||
|
#endif /* __GNUC__ && __arm__ */
|
||||||
|
#else
|
||||||
|
#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
|
||||||
|
/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */
|
||||||
|
#include <mbarrier.h>
|
||||||
|
#define SDL_MemoryBarrierRelease() __machine_rel_barrier()
|
||||||
|
#define SDL_MemoryBarrierAcquire() __machine_acq_barrier()
|
||||||
|
#else
|
||||||
|
/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
|
||||||
|
#define SDL_MemoryBarrierRelease() SDL_CompilerBarrier()
|
||||||
|
#define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to insert a CPU-specific "pause" instruction into the program.
|
||||||
|
*
|
||||||
|
* This can be useful in busy-wait loops, as it serves as a hint to the CPU as
|
||||||
|
* to the program's intent; some CPUs can use this to do more efficient
|
||||||
|
* processing. On some platforms, this doesn't do anything, so using this
|
||||||
|
* macro might just be a harmless no-op.
|
||||||
|
*
|
||||||
|
* Note that if you are busy-waiting, there are often more-efficient
|
||||||
|
* approaches with other synchronization primitives: mutexes, semaphores,
|
||||||
|
* condition variables, etc.
|
||||||
|
*
|
||||||
|
* \threadsafety This macro is safe to use from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_CPUPauseInstruction() DoACPUPauseInACompilerAndArchitectureSpecificWay
|
||||||
|
|
||||||
|
#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
|
||||||
|
#define SDL_CPUPauseInstruction() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */
|
||||||
|
#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7) || defined(__aarch64__)
|
||||||
|
#define SDL_CPUPauseInstruction() __asm__ __volatile__("yield" ::: "memory")
|
||||||
|
#elif (defined(__powerpc__) || defined(__powerpc64__))
|
||||||
|
#define SDL_CPUPauseInstruction() __asm__ __volatile__("or 27,27,27");
|
||||||
|
#elif (defined(__riscv) && __riscv_xlen == 64)
|
||||||
|
#define SDL_CPUPauseInstruction() __asm__ __volatile__(".insn i 0x0F, 0, x0, x0, 0x010");
|
||||||
|
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||||
|
#define SDL_CPUPauseInstruction() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */
|
||||||
|
#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||||
|
#define SDL_CPUPauseInstruction() __yield()
|
||||||
|
#elif defined(__WATCOMC__) && defined(__386__)
|
||||||
|
extern __inline void SDL_CPUPauseInstruction(void);
|
||||||
|
#pragma aux SDL_CPUPauseInstruction = ".686p" ".xmm2" "pause"
|
||||||
|
#else
|
||||||
|
#define SDL_CPUPauseInstruction()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type representing an atomic integer value.
|
||||||
|
*
|
||||||
|
* This can be used to manage a value that is synchronized across multiple
|
||||||
|
* CPUs without a race condition; when an app sets a value with
|
||||||
|
* SDL_SetAtomicInt all other threads, regardless of the CPU it is running on,
|
||||||
|
* will see that value when retrieved with SDL_GetAtomicInt, regardless of CPU
|
||||||
|
* caches, etc.
|
||||||
|
*
|
||||||
|
* This is also useful for atomic compare-and-swap operations: a thread can
|
||||||
|
* change the value as long as its current value matches expectations. When
|
||||||
|
* done in a loop, one can guarantee data consistency across threads without a
|
||||||
|
* lock (but the usual warnings apply: if you don't know what you're doing, or
|
||||||
|
* you don't do it carefully, you can confidently cause any number of
|
||||||
|
* disasters with this, so in most cases, you _should_ use a mutex instead of
|
||||||
|
* this!).
|
||||||
|
*
|
||||||
|
* This is a struct so people don't accidentally use numeric operations on it
|
||||||
|
* directly. You have to use SDL atomic functions.
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_CompareAndSwapAtomicInt
|
||||||
|
* \sa SDL_GetAtomicInt
|
||||||
|
* \sa SDL_SetAtomicInt
|
||||||
|
* \sa SDL_AddAtomicInt
|
||||||
|
*/
|
||||||
|
typedef struct SDL_AtomicInt { int value; } SDL_AtomicInt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an atomic variable to a new value if it is currently an old value.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicInt variable to be modified.
|
||||||
|
* \param oldval the old value.
|
||||||
|
* \param newval the new value.
|
||||||
|
* \returns true if the atomic variable was set, false otherwise.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetAtomicInt
|
||||||
|
* \sa SDL_SetAtomicInt
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_CompareAndSwapAtomicInt(SDL_AtomicInt *a, int oldval, int newval);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an atomic variable to a value.
|
||||||
|
*
|
||||||
|
* This function also acts as a full memory barrier.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicInt variable to be modified.
|
||||||
|
* \param v the desired value.
|
||||||
|
* \returns the previous value of the atomic variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetAtomicInt
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC int SDLCALL SDL_SetAtomicInt(SDL_AtomicInt *a, int v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of an atomic variable.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicInt variable.
|
||||||
|
* \returns the current value of an atomic variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_SetAtomicInt
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC int SDLCALL SDL_GetAtomicInt(SDL_AtomicInt *a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add to an atomic variable.
|
||||||
|
*
|
||||||
|
* This function also acts as a full memory barrier.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicInt variable to be modified.
|
||||||
|
* \param v the desired value to add.
|
||||||
|
* \returns the previous value of the atomic variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_AtomicDecRef
|
||||||
|
* \sa SDL_AtomicIncRef
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC int SDLCALL SDL_AddAtomicInt(SDL_AtomicInt *a, int v);
|
||||||
|
|
||||||
|
#ifndef SDL_AtomicIncRef
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment an atomic variable used as a reference count.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this macro is for, you shouldn't use it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicInt to increment.
|
||||||
|
* \returns the previous value of the atomic variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this macro from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_AtomicDecRef
|
||||||
|
*/
|
||||||
|
#define SDL_AtomicIncRef(a) SDL_AddAtomicInt(a, 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_AtomicDecRef
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrement an atomic variable used as a reference count.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this macro is for, you shouldn't use it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicInt to decrement.
|
||||||
|
* \returns true if the variable reached zero after decrementing, false
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this macro from any thread.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_AtomicIncRef
|
||||||
|
*/
|
||||||
|
#define SDL_AtomicDecRef(a) (SDL_AddAtomicInt(a, -1) == 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type representing an atomic unsigned 32-bit value.
|
||||||
|
*
|
||||||
|
* This can be used to manage a value that is synchronized across multiple
|
||||||
|
* CPUs without a race condition; when an app sets a value with
|
||||||
|
* SDL_SetAtomicU32 all other threads, regardless of the CPU it is running on,
|
||||||
|
* will see that value when retrieved with SDL_GetAtomicU32, regardless of CPU
|
||||||
|
* caches, etc.
|
||||||
|
*
|
||||||
|
* This is also useful for atomic compare-and-swap operations: a thread can
|
||||||
|
* change the value as long as its current value matches expectations. When
|
||||||
|
* done in a loop, one can guarantee data consistency across threads without a
|
||||||
|
* lock (but the usual warnings apply: if you don't know what you're doing, or
|
||||||
|
* you don't do it carefully, you can confidently cause any number of
|
||||||
|
* disasters with this, so in most cases, you _should_ use a mutex instead of
|
||||||
|
* this!).
|
||||||
|
*
|
||||||
|
* This is a struct so people don't accidentally use numeric operations on it
|
||||||
|
* directly. You have to use SDL atomic functions.
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_CompareAndSwapAtomicU32
|
||||||
|
* \sa SDL_GetAtomicU32
|
||||||
|
* \sa SDL_SetAtomicU32
|
||||||
|
*/
|
||||||
|
typedef struct SDL_AtomicU32 { Uint32 value; } SDL_AtomicU32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an atomic variable to a new value if it is currently an old value.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicU32 variable to be modified.
|
||||||
|
* \param oldval the old value.
|
||||||
|
* \param newval the new value.
|
||||||
|
* \returns true if the atomic variable was set, false otherwise.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetAtomicU32
|
||||||
|
* \sa SDL_SetAtomicU32
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_CompareAndSwapAtomicU32(SDL_AtomicU32 *a, Uint32 oldval, Uint32 newval);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an atomic variable to a value.
|
||||||
|
*
|
||||||
|
* This function also acts as a full memory barrier.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicU32 variable to be modified.
|
||||||
|
* \param v the desired value.
|
||||||
|
* \returns the previous value of the atomic variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetAtomicU32
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC Uint32 SDLCALL SDL_SetAtomicU32(SDL_AtomicU32 *a, Uint32 v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of an atomic variable.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to an SDL_AtomicU32 variable.
|
||||||
|
* \returns the current value of an atomic variable.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_SetAtomicU32
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetAtomicU32(SDL_AtomicU32 *a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a pointer to a new value if it is currently an old value.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to a pointer.
|
||||||
|
* \param oldval the old pointer value.
|
||||||
|
* \param newval the new pointer value.
|
||||||
|
* \returns true if the pointer was set, false otherwise.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_CompareAndSwapAtomicInt
|
||||||
|
* \sa SDL_GetAtomicPointer
|
||||||
|
* \sa SDL_SetAtomicPointer
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_CompareAndSwapAtomicPointer(void **a, void *oldval, void *newval);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a pointer to a value atomically.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to a pointer.
|
||||||
|
* \param v the desired pointer value.
|
||||||
|
* \returns the previous value of the pointer.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_CompareAndSwapAtomicPointer
|
||||||
|
* \sa SDL_GetAtomicPointer
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void * SDLCALL SDL_SetAtomicPointer(void **a, void *v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a pointer atomically.
|
||||||
|
*
|
||||||
|
* ***Note: If you don't know what this function is for, you shouldn't use
|
||||||
|
* it!***
|
||||||
|
*
|
||||||
|
* \param a a pointer to a pointer.
|
||||||
|
* \returns the current value of a pointer.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_CompareAndSwapAtomicPointer
|
||||||
|
* \sa SDL_SetAtomicPointer
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void * SDLCALL SDL_GetAtomicPointer(void **a);
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <SDL3/SDL_close_code.h>
|
||||||
|
|
||||||
|
#endif /* SDL_atomic_h_ */
|
||||||
@@ -0,0 +1,486 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WIKI CATEGORY: BeginCode */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # CategoryBeginCode
|
||||||
|
*
|
||||||
|
* `SDL_begin_code.h` sets things up for C dynamic library function
|
||||||
|
* definitions, static inlined functions, and structures aligned at 4-byte
|
||||||
|
* alignment. If you don't like ugly C preprocessor code, don't look at this
|
||||||
|
* file. :)
|
||||||
|
*
|
||||||
|
* SDL's headers use this; applications generally should not include this
|
||||||
|
* header directly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This shouldn't be nested -- included it around code only. */
|
||||||
|
#ifdef SDL_begin_code_h
|
||||||
|
#error Nested inclusion of SDL_begin_code.h
|
||||||
|
#endif
|
||||||
|
#define SDL_begin_code_h
|
||||||
|
|
||||||
|
#ifdef SDL_WIKI_DOCUMENTATION_SECTION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a symbol as deprecated.
|
||||||
|
*
|
||||||
|
* A function is marked deprecated by adding this macro to its declaration:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* extern SDL_DEPRECATED int ThisFunctionWasABadIdea(void);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Compilers with deprecation support can give a warning when a deprecated
|
||||||
|
* function is used. This symbol may be used in SDL's headers, but apps are
|
||||||
|
* welcome to use it for their own interfaces as well.
|
||||||
|
*
|
||||||
|
* SDL, on occasion, might deprecate a function for various reasons. However,
|
||||||
|
* SDL never removes symbols before major versions, so deprecated interfaces
|
||||||
|
* in SDL3 will remain available until SDL4, where it would be expected an app
|
||||||
|
* would have to take steps to migrate anyhow.
|
||||||
|
*
|
||||||
|
* On compilers without a deprecation mechanism, this is defined to nothing,
|
||||||
|
* and using a deprecated function will not generate a warning.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_DEPRECATED __attribute__((deprecated))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a symbol as a public API.
|
||||||
|
*
|
||||||
|
* SDL uses this macro for all its public functions. On some targets, it is
|
||||||
|
* used to signal to the compiler that this function needs to be exported from
|
||||||
|
* a shared library, but it might have other side effects.
|
||||||
|
*
|
||||||
|
* This symbol is used in SDL's headers, but apps and other libraries are
|
||||||
|
* welcome to use it for their own interfaces as well.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_DECLSPEC __attribute__ ((visibility("default")))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to set a function's calling conventions.
|
||||||
|
*
|
||||||
|
* SDL uses this macro for all its public functions, and any callbacks it
|
||||||
|
* defines. This macro guarantees that calling conventions match between SDL
|
||||||
|
* and the app, even if the two were built with different compilers or
|
||||||
|
* optimization settings.
|
||||||
|
*
|
||||||
|
* When writing a callback function, it is very important for it to be
|
||||||
|
* correctly tagged with SDLCALL, as mismatched calling conventions can cause
|
||||||
|
* strange behaviors and can be difficult to diagnose. Plus, on many
|
||||||
|
* platforms, SDLCALL is defined to nothing, so compilers won't be able to
|
||||||
|
* warn that the tag is missing.
|
||||||
|
*
|
||||||
|
* This symbol is used in SDL's headers, but apps and other libraries are
|
||||||
|
* welcome to use it for their own interfaces as well.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDLCALL __cdecl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to request a function be inlined.
|
||||||
|
*
|
||||||
|
* This is a hint to the compiler to inline a function. The compiler is free
|
||||||
|
* to ignore this request. On compilers without inline support, this is
|
||||||
|
* defined to nothing.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_INLINE __inline
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to demand a function be inlined.
|
||||||
|
*
|
||||||
|
* This is a command to the compiler to inline a function. SDL uses this macro
|
||||||
|
* in its public headers for a handful of simple functions. On compilers
|
||||||
|
* without forceinline support, this is defined to `static SDL_INLINE`, which
|
||||||
|
* is often good enough.
|
||||||
|
*
|
||||||
|
* This symbol is used in SDL's headers, but apps and other libraries are
|
||||||
|
* welcome to use it for their own interfaces as well.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_FORCE_INLINE __forceinline
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a function as never-returning.
|
||||||
|
*
|
||||||
|
* This is a hint to the compiler that a function does not return. An example
|
||||||
|
* of a function like this is the C runtime's exit() function.
|
||||||
|
*
|
||||||
|
* This hint can lead to code optimizations, and help analyzers understand
|
||||||
|
* code flow better. On compilers without noreturn support, this is defined to
|
||||||
|
* nothing.
|
||||||
|
*
|
||||||
|
* This symbol is used in SDL's headers, but apps and other libraries are
|
||||||
|
* welcome to use it for their own interfaces as well.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_NORETURN __attribute__((noreturn))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a function as never-returning (for analysis purposes).
|
||||||
|
*
|
||||||
|
* This is almost identical to SDL_NORETURN, except functions marked with this
|
||||||
|
* _can_ actually return. The difference is that this isn't used for code
|
||||||
|
* generation, but rather static analyzers use this information to assume
|
||||||
|
* truths about program state and available code paths. Specifically, this tag
|
||||||
|
* is useful for writing an assertion mechanism. Indeed, SDL_assert uses this
|
||||||
|
* tag behind the scenes. Generally, apps that don't understand the specific
|
||||||
|
* use-case for this tag should avoid using it directly.
|
||||||
|
*
|
||||||
|
* On compilers without analyzer_noreturn support, this is defined to nothing.
|
||||||
|
*
|
||||||
|
* This symbol is used in SDL's headers, but apps and other libraries are
|
||||||
|
* welcome to use it for their own interfaces as well.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to signal that a case statement without a `break` is intentional.
|
||||||
|
*
|
||||||
|
* C compilers have gotten more aggressive about warning when a switch's
|
||||||
|
* `case` block does not end with a `break` or other flow control statement,
|
||||||
|
* flowing into the next case's code, as this is a common accident that leads
|
||||||
|
* to strange bugs. But sometimes falling through to the next case is the
|
||||||
|
* correct and desired behavior. This symbol lets an app communicate this
|
||||||
|
* intention to the compiler, so it doesn't generate a warning.
|
||||||
|
*
|
||||||
|
* It is used like this:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* switch (x) {
|
||||||
|
* case 1:
|
||||||
|
* DoSomethingOnlyForOne();
|
||||||
|
* SDL_FALLTHROUGH; // tell the compiler this was intentional.
|
||||||
|
* case 2:
|
||||||
|
* DoSomethingForOneAndTwo();
|
||||||
|
* break;
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_FALLTHROUGH [[fallthrough]]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a function's return value as critical.
|
||||||
|
*
|
||||||
|
* This is a hint to the compiler that a function's return value should not be
|
||||||
|
* ignored.
|
||||||
|
*
|
||||||
|
* If an NODISCARD function's return value is thrown away (the function is
|
||||||
|
* called as if it returns `void`), the compiler will issue a warning.
|
||||||
|
*
|
||||||
|
* While it's generally good practice to check return values for errors, often
|
||||||
|
* times legitimate programs do not for good reasons. Be careful about what
|
||||||
|
* functions are tagged as NODISCARD. It operates best when used on a function
|
||||||
|
* that's failure is surprising and catastrophic; a good example would be a
|
||||||
|
* program that checks the return values of all its file write function calls
|
||||||
|
* but not the call to close the file, which it assumes incorrectly never
|
||||||
|
* fails.
|
||||||
|
*
|
||||||
|
* Function callers that want to throw away a NODISCARD return value can call
|
||||||
|
* the function with a `(void)` cast, which informs the compiler the act is
|
||||||
|
* intentional.
|
||||||
|
*
|
||||||
|
* On compilers without nodiscard support, this is defined to nothing.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_NODISCARD [[nodiscard]]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a function as an allocator.
|
||||||
|
*
|
||||||
|
* This is a hint to the compiler that a function is an allocator, like
|
||||||
|
* malloc(), with certain rules. A description of how GCC treats this hint is
|
||||||
|
* here:
|
||||||
|
*
|
||||||
|
* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute
|
||||||
|
*
|
||||||
|
* On compilers without allocator tag support, this is defined to nothing.
|
||||||
|
*
|
||||||
|
* Most apps don't need to, and should not, use this directly.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_MALLOC __declspec(allocator) __desclspec(restrict)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a function as returning a certain allocation.
|
||||||
|
*
|
||||||
|
* This is a hint to the compiler that a function allocates and returns a
|
||||||
|
* specific amount of memory based on one of its arguments. For example, the C
|
||||||
|
* runtime's malloc() function could use this macro with an argument of 1
|
||||||
|
* (first argument to malloc is the size of the allocation).
|
||||||
|
*
|
||||||
|
* On compilers without alloc_size support, this is defined to nothing.
|
||||||
|
*
|
||||||
|
* Most apps don't need to, and should not, use this directly.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A macro to tag a pointer variable, to help with pointer aliasing.
|
||||||
|
*
|
||||||
|
* A good explanation of the restrict keyword is here:
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/Restrict
|
||||||
|
*
|
||||||
|
* On compilers without restrict support, this is defined to nothing.
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_RESTRICT __restrict__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the compiler supports a given builtin functionality.
|
||||||
|
*
|
||||||
|
* This allows preprocessor checks for things that otherwise might fail to
|
||||||
|
* compile.
|
||||||
|
*
|
||||||
|
* Supported by virtually all clang versions and more-recent GCCs. Use this
|
||||||
|
* instead of checking the clang version if possible.
|
||||||
|
*
|
||||||
|
* On compilers without has_builtin support, this is defined to 0 (always
|
||||||
|
* false).
|
||||||
|
*
|
||||||
|
* \since This macro is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
#define SDL_HAS_BUILTIN(x) __has_builtin(x)
|
||||||
|
|
||||||
|
/* end of wiki documentation section. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_HAS_BUILTIN
|
||||||
|
#ifdef __has_builtin
|
||||||
|
#define SDL_HAS_BUILTIN(x) __has_builtin(x)
|
||||||
|
#else
|
||||||
|
#define SDL_HAS_BUILTIN(x) 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_DEPRECATED
|
||||||
|
# if defined(__GNUC__) && (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */
|
||||||
|
# define SDL_DEPRECATED __attribute__((deprecated))
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# define SDL_DEPRECATED __declspec(deprecated)
|
||||||
|
# else
|
||||||
|
# define SDL_DEPRECATED
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_UNUSED
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# define SDL_UNUSED __attribute__((unused))
|
||||||
|
# else
|
||||||
|
# define SDL_UNUSED
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some compilers use a special export keyword */
|
||||||
|
#ifndef SDL_DECLSPEC
|
||||||
|
# if defined(SDL_PLATFORM_WINDOWS)
|
||||||
|
# ifdef DLL_EXPORT
|
||||||
|
# define SDL_DECLSPEC __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define SDL_DECLSPEC
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# if defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
# define SDL_DECLSPEC __attribute__ ((visibility("default")))
|
||||||
|
# else
|
||||||
|
# define SDL_DECLSPEC
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* By default SDL uses the C calling convention */
|
||||||
|
#ifndef SDLCALL
|
||||||
|
#if defined(SDL_PLATFORM_WINDOWS) && !defined(__GNUC__)
|
||||||
|
#define SDLCALL __cdecl
|
||||||
|
#else
|
||||||
|
#define SDLCALL
|
||||||
|
#endif
|
||||||
|
#endif /* SDLCALL */
|
||||||
|
|
||||||
|
/* Force structure packing at 4 byte alignment.
|
||||||
|
This is necessary if the header is included in code which has structure
|
||||||
|
packing set to an alternate value, say for loading structures from disk.
|
||||||
|
The packing is reset to the previous value in SDL_close_code.h
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4103)
|
||||||
|
#endif
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic ignored "-Wpragma-pack"
|
||||||
|
#endif
|
||||||
|
#ifdef __BORLANDC__
|
||||||
|
#pragma nopackwarning
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN64
|
||||||
|
/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */
|
||||||
|
#pragma pack(push,8)
|
||||||
|
#else
|
||||||
|
#pragma pack(push,4)
|
||||||
|
#endif
|
||||||
|
#endif /* Compiler needs structure packing set */
|
||||||
|
|
||||||
|
#ifndef SDL_INLINE
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define SDL_INLINE __inline__
|
||||||
|
#elif defined(_MSC_VER) || defined(__BORLANDC__) || \
|
||||||
|
defined(__DMC__) || defined(__SC__) || \
|
||||||
|
defined(__WATCOMC__) || defined(__LCC__) || \
|
||||||
|
defined(__DECC) || defined(__CC_ARM)
|
||||||
|
#define SDL_INLINE __inline
|
||||||
|
#ifndef __inline__
|
||||||
|
#define __inline__ __inline
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SDL_INLINE inline
|
||||||
|
#ifndef __inline__
|
||||||
|
#define __inline__ inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif /* SDL_INLINE not defined */
|
||||||
|
|
||||||
|
#ifndef SDL_FORCE_INLINE
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define SDL_FORCE_INLINE __forceinline
|
||||||
|
#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
|
||||||
|
#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__
|
||||||
|
#else
|
||||||
|
#define SDL_FORCE_INLINE static SDL_INLINE
|
||||||
|
#endif
|
||||||
|
#endif /* SDL_FORCE_INLINE not defined */
|
||||||
|
|
||||||
|
#ifndef SDL_NORETURN
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define SDL_NORETURN __attribute__((noreturn))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define SDL_NORETURN __declspec(noreturn)
|
||||||
|
#else
|
||||||
|
#define SDL_NORETURN
|
||||||
|
#endif
|
||||||
|
#endif /* SDL_NORETURN not defined */
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#if __has_feature(attribute_analyzer_noreturn)
|
||||||
|
#define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_ANALYZER_NORETURN
|
||||||
|
#define SDL_ANALYZER_NORETURN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Apparently this is needed by several Windows compilers */
|
||||||
|
#ifndef __MACH__
|
||||||
|
#ifndef NULL
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define NULL 0
|
||||||
|
#else
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
#endif
|
||||||
|
#endif /* NULL */
|
||||||
|
#endif /* ! macOS - breaks precompiled headers */
|
||||||
|
|
||||||
|
#ifndef SDL_FALLTHROUGH
|
||||||
|
#if (defined(__cplusplus) && __cplusplus >= 201703L) || \
|
||||||
|
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L)
|
||||||
|
#define SDL_FALLTHROUGH [[fallthrough]]
|
||||||
|
#else
|
||||||
|
#if defined(__has_attribute) && !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
|
||||||
|
#define SDL_HAS_FALLTHROUGH __has_attribute(__fallthrough__)
|
||||||
|
#else
|
||||||
|
#define SDL_HAS_FALLTHROUGH 0
|
||||||
|
#endif /* __has_attribute */
|
||||||
|
#if SDL_HAS_FALLTHROUGH && \
|
||||||
|
((defined(__GNUC__) && __GNUC__ >= 7) || \
|
||||||
|
(defined(__clang_major__) && __clang_major__ >= 10))
|
||||||
|
#define SDL_FALLTHROUGH __attribute__((__fallthrough__))
|
||||||
|
#else
|
||||||
|
#define SDL_FALLTHROUGH do {} while (0) /* fallthrough */
|
||||||
|
#endif /* SDL_HAS_FALLTHROUGH */
|
||||||
|
#undef SDL_HAS_FALLTHROUGH
|
||||||
|
#endif /* C++17 or C2x */
|
||||||
|
#endif /* SDL_FALLTHROUGH not defined */
|
||||||
|
|
||||||
|
#ifndef SDL_NODISCARD
|
||||||
|
#if (defined(__cplusplus) && __cplusplus >= 201703L) || \
|
||||||
|
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
|
||||||
|
#define SDL_NODISCARD [[nodiscard]]
|
||||||
|
#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
|
||||||
|
#define SDL_NODISCARD __attribute__((warn_unused_result))
|
||||||
|
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
|
||||||
|
#define SDL_NODISCARD _Check_return_
|
||||||
|
#else
|
||||||
|
#define SDL_NODISCARD
|
||||||
|
#endif /* C++17 or C23 */
|
||||||
|
#endif /* SDL_NODISCARD not defined */
|
||||||
|
|
||||||
|
#ifndef SDL_MALLOC
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||||
|
#define SDL_MALLOC __attribute__((malloc))
|
||||||
|
/** FIXME
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define SDL_MALLOC __declspec(allocator) __desclspec(restrict)
|
||||||
|
**/
|
||||||
|
#else
|
||||||
|
#define SDL_MALLOC
|
||||||
|
#endif
|
||||||
|
#endif /* SDL_MALLOC not defined */
|
||||||
|
|
||||||
|
#ifndef SDL_ALLOC_SIZE
|
||||||
|
#if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
|
||||||
|
#define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p)))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define SDL_ALLOC_SIZE(p)
|
||||||
|
#else
|
||||||
|
#define SDL_ALLOC_SIZE(p)
|
||||||
|
#endif
|
||||||
|
#endif /* SDL_ALLOC_SIZE not defined */
|
||||||
|
|
||||||
|
#ifndef SDL_ALLOC_SIZE2
|
||||||
|
#if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
|
||||||
|
#define SDL_ALLOC_SIZE2(p1, p2) __attribute__((alloc_size(p1, p2)))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define SDL_ALLOC_SIZE2(p1, p2)
|
||||||
|
#else
|
||||||
|
#define SDL_ALLOC_SIZE2(p1, p2)
|
||||||
|
#endif
|
||||||
|
#endif /* SDL_ALLOC_SIZE2 not defined */
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # CategoryBits
|
||||||
|
*
|
||||||
|
* Functions for fiddling with bits and bitmasks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_bits_h_
|
||||||
|
#define SDL_bits_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__WATCOMC__) && defined(__386__)
|
||||||
|
extern __inline int _SDL_bsr_watcom(Uint32);
|
||||||
|
#pragma aux _SDL_bsr_watcom = \
|
||||||
|
"bsr eax, eax" \
|
||||||
|
parm [eax] nomemory \
|
||||||
|
value [eax] \
|
||||||
|
modify exact [eax] nomemory;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of the most significant (set) bit in a 32-bit number.
|
||||||
|
*
|
||||||
|
* Result is undefined when called with 0. This operation can also be stated
|
||||||
|
* as "count leading zeroes" and "log base 2".
|
||||||
|
*
|
||||||
|
* Note that this is a forced-inline function in a header, and not a public
|
||||||
|
* API function available in the SDL library (which is to say, the code is
|
||||||
|
* embedded in the calling program and the linker and dynamic loader will not
|
||||||
|
* be able to find this function inside SDL itself).
|
||||||
|
*
|
||||||
|
* \param x the 32-bit value to examine.
|
||||||
|
* \returns the index of the most significant bit, or -1 if the value is 0.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
SDL_FORCE_INLINE int SDL_MostSignificantBitIndex32(Uint32 x)
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
|
||||||
|
/* Count Leading Zeroes builtin in GCC.
|
||||||
|
* http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html
|
||||||
|
*/
|
||||||
|
if (x == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 31 - __builtin_clz(x);
|
||||||
|
#elif defined(__WATCOMC__) && defined(__386__)
|
||||||
|
if (x == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return _SDL_bsr_watcom(x);
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
|
unsigned long index;
|
||||||
|
if (_BitScanReverse(&index, x)) {
|
||||||
|
return (int)index;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
/* Based off of Bit Twiddling Hacks by Sean Eron Anderson
|
||||||
|
* <seander@cs.stanford.edu>, released in the public domain.
|
||||||
|
* http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
|
||||||
|
*/
|
||||||
|
const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
|
||||||
|
const int S[] = {1, 2, 4, 8, 16};
|
||||||
|
|
||||||
|
int msbIndex = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (x == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 4; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (x & b[i])
|
||||||
|
{
|
||||||
|
x >>= S[i];
|
||||||
|
msbIndex |= S[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return msbIndex;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a unsigned 32-bit value has exactly one bit set.
|
||||||
|
*
|
||||||
|
* If there are no bits set (`x` is zero), or more than one bit set, this
|
||||||
|
* returns false. If any one bit is exclusively set, this returns true.
|
||||||
|
*
|
||||||
|
* Note that this is a forced-inline function in a header, and not a public
|
||||||
|
* API function available in the SDL library (which is to say, the code is
|
||||||
|
* embedded in the calling program and the linker and dynamic loader will not
|
||||||
|
* be able to find this function inside SDL itself).
|
||||||
|
*
|
||||||
|
* \param x the 32-bit value to examine.
|
||||||
|
* \returns true if exactly one bit is set in `x`, false otherwise.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
SDL_FORCE_INLINE bool SDL_HasExactlyOneBitSet32(Uint32 x)
|
||||||
|
{
|
||||||
|
if (x && !(x & (x - 1))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <SDL3/SDL_close_code.h>
|
||||||
|
|
||||||
|
#endif /* SDL_bits_h_ */
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # CategoryBlendmode
|
||||||
|
*
|
||||||
|
* Blend modes decide how two colors will mix together. There are both
|
||||||
|
* standard modes for basic needs and a means to create custom modes,
|
||||||
|
* dictating what sort of math to do on what color components.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_blendmode_h_
|
||||||
|
#define SDL_blendmode_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of blend modes used in drawing operations.
|
||||||
|
*
|
||||||
|
* These predefined blend modes are supported everywhere.
|
||||||
|
*
|
||||||
|
* Additional values may be obtained from SDL_ComposeCustomBlendMode.
|
||||||
|
*
|
||||||
|
* \since This datatype is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_ComposeCustomBlendMode
|
||||||
|
*/
|
||||||
|
typedef Uint32 SDL_BlendMode;
|
||||||
|
|
||||||
|
#define SDL_BLENDMODE_NONE 0x00000000u /**< no blending: dstRGBA = srcRGBA */
|
||||||
|
#define SDL_BLENDMODE_BLEND 0x00000001u /**< alpha blending: dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA)), dstA = srcA + (dstA * (1-srcA)) */
|
||||||
|
#define SDL_BLENDMODE_BLEND_PREMULTIPLIED 0x00000010u /**< pre-multiplied alpha blending: dstRGBA = srcRGBA + (dstRGBA * (1-srcA)) */
|
||||||
|
#define SDL_BLENDMODE_ADD 0x00000002u /**< additive blending: dstRGB = (srcRGB * srcA) + dstRGB, dstA = dstA */
|
||||||
|
#define SDL_BLENDMODE_ADD_PREMULTIPLIED 0x00000020u /**< pre-multiplied additive blending: dstRGB = srcRGB + dstRGB, dstA = dstA */
|
||||||
|
#define SDL_BLENDMODE_MOD 0x00000004u /**< color modulate: dstRGB = srcRGB * dstRGB, dstA = dstA */
|
||||||
|
#define SDL_BLENDMODE_MUL 0x00000008u /**< color multiply: dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA)), dstA = dstA */
|
||||||
|
#define SDL_BLENDMODE_INVALID 0x7FFFFFFFu
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The blend operation used when combining source and destination pixel
|
||||||
|
* components.
|
||||||
|
*
|
||||||
|
* \since This enum is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef enum SDL_BlendOperation
|
||||||
|
{
|
||||||
|
SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */
|
||||||
|
SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< src - dst : supported by D3D, OpenGL, OpenGLES, and Vulkan */
|
||||||
|
SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< dst - src : supported by D3D, OpenGL, OpenGLES, and Vulkan */
|
||||||
|
SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D, OpenGL, OpenGLES, and Vulkan */
|
||||||
|
SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D, OpenGL, OpenGLES, and Vulkan */
|
||||||
|
} SDL_BlendOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The normalized factor used to multiply pixel components.
|
||||||
|
*
|
||||||
|
* The blend factors are multiplied with the pixels from a drawing operation
|
||||||
|
* (src) and the pixels from the render target (dst) before the blend
|
||||||
|
* operation. The comma-separated factors listed above are always applied in
|
||||||
|
* the component order red, green, blue, and alpha.
|
||||||
|
*
|
||||||
|
* \since This enum is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef enum SDL_BlendFactor
|
||||||
|
{
|
||||||
|
SDL_BLENDFACTOR_ZERO = 0x1, /**< 0, 0, 0, 0 */
|
||||||
|
SDL_BLENDFACTOR_ONE = 0x2, /**< 1, 1, 1, 1 */
|
||||||
|
SDL_BLENDFACTOR_SRC_COLOR = 0x3, /**< srcR, srcG, srcB, srcA */
|
||||||
|
SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4, /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */
|
||||||
|
SDL_BLENDFACTOR_SRC_ALPHA = 0x5, /**< srcA, srcA, srcA, srcA */
|
||||||
|
SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6, /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */
|
||||||
|
SDL_BLENDFACTOR_DST_COLOR = 0x7, /**< dstR, dstG, dstB, dstA */
|
||||||
|
SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
|
||||||
|
SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */
|
||||||
|
SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
|
||||||
|
} SDL_BlendFactor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose a custom blend mode for renderers.
|
||||||
|
*
|
||||||
|
* The functions SDL_SetRenderDrawBlendMode and SDL_SetTextureBlendMode accept
|
||||||
|
* the SDL_BlendMode returned by this function if the renderer supports it.
|
||||||
|
*
|
||||||
|
* A blend mode controls how the pixels from a drawing operation (source) get
|
||||||
|
* combined with the pixels from the render target (destination). First, the
|
||||||
|
* components of the source and destination pixels get multiplied with their
|
||||||
|
* blend factors. Then, the blend operation takes the two products and
|
||||||
|
* calculates the result that will get stored in the render target.
|
||||||
|
*
|
||||||
|
* Expressed in pseudocode, it would look like this:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* dstRGB = colorOperation(srcRGB * srcColorFactor, dstRGB * dstColorFactor);
|
||||||
|
* dstA = alphaOperation(srcA * srcAlphaFactor, dstA * dstAlphaFactor);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Where the functions `colorOperation(src, dst)` and `alphaOperation(src,
|
||||||
|
* dst)` can return one of the following:
|
||||||
|
*
|
||||||
|
* - `src + dst`
|
||||||
|
* - `src - dst`
|
||||||
|
* - `dst - src`
|
||||||
|
* - `min(src, dst)`
|
||||||
|
* - `max(src, dst)`
|
||||||
|
*
|
||||||
|
* The red, green, and blue components are always multiplied with the first,
|
||||||
|
* second, and third components of the SDL_BlendFactor, respectively. The
|
||||||
|
* fourth component is not used.
|
||||||
|
*
|
||||||
|
* The alpha component is always multiplied with the fourth component of the
|
||||||
|
* SDL_BlendFactor. The other components are not used in the alpha
|
||||||
|
* calculation.
|
||||||
|
*
|
||||||
|
* Support for these blend modes varies for each renderer. To check if a
|
||||||
|
* specific SDL_BlendMode is supported, create a renderer and pass it to
|
||||||
|
* either SDL_SetRenderDrawBlendMode or SDL_SetTextureBlendMode. They will
|
||||||
|
* return with an error if the blend mode is not supported.
|
||||||
|
*
|
||||||
|
* This list describes the support of custom blend modes for each renderer.
|
||||||
|
* All renderers support the four blend modes listed in the SDL_BlendMode
|
||||||
|
* enumeration.
|
||||||
|
*
|
||||||
|
* - **direct3d**: Supports all operations with all factors. However, some
|
||||||
|
* factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and
|
||||||
|
* `SDL_BLENDOPERATION_MAXIMUM`.
|
||||||
|
* - **direct3d11**: Same as Direct3D 9.
|
||||||
|
* - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
|
||||||
|
* factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly here.
|
||||||
|
* - **opengles2**: Supports the `SDL_BLENDOPERATION_ADD`,
|
||||||
|
* `SDL_BLENDOPERATION_SUBTRACT`, `SDL_BLENDOPERATION_REV_SUBTRACT`
|
||||||
|
* operations with all factors.
|
||||||
|
* - **psp**: No custom blend mode support.
|
||||||
|
* - **software**: No custom blend mode support.
|
||||||
|
*
|
||||||
|
* Some renderers do not provide an alpha component for the default render
|
||||||
|
* target. The `SDL_BLENDFACTOR_DST_ALPHA` and
|
||||||
|
* `SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA` factors do not have an effect in this
|
||||||
|
* case.
|
||||||
|
*
|
||||||
|
* \param srcColorFactor the SDL_BlendFactor applied to the red, green, and
|
||||||
|
* blue components of the source pixels.
|
||||||
|
* \param dstColorFactor the SDL_BlendFactor applied to the red, green, and
|
||||||
|
* blue components of the destination pixels.
|
||||||
|
* \param colorOperation the SDL_BlendOperation used to combine the red,
|
||||||
|
* green, and blue components of the source and
|
||||||
|
* destination pixels.
|
||||||
|
* \param srcAlphaFactor the SDL_BlendFactor applied to the alpha component of
|
||||||
|
* the source pixels.
|
||||||
|
* \param dstAlphaFactor the SDL_BlendFactor applied to the alpha component of
|
||||||
|
* the destination pixels.
|
||||||
|
* \param alphaOperation the SDL_BlendOperation used to combine the alpha
|
||||||
|
* component of the source and destination pixels.
|
||||||
|
* \returns an SDL_BlendMode that represents the chosen factors and
|
||||||
|
* operations.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_SetRenderDrawBlendMode
|
||||||
|
* \sa SDL_GetRenderDrawBlendMode
|
||||||
|
* \sa SDL_SetTextureBlendMode
|
||||||
|
* \sa SDL_GetTextureBlendMode
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_BlendMode SDLCALL SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor,
|
||||||
|
SDL_BlendFactor dstColorFactor,
|
||||||
|
SDL_BlendOperation colorOperation,
|
||||||
|
SDL_BlendFactor srcAlphaFactor,
|
||||||
|
SDL_BlendFactor dstAlphaFactor,
|
||||||
|
SDL_BlendOperation alphaOperation);
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <SDL3/SDL_close_code.h>
|
||||||
|
|
||||||
|
#endif /* SDL_blendmode_h_ */
|
||||||
@@ -0,0 +1,519 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # CategoryCamera
|
||||||
|
*
|
||||||
|
* Video capture for the SDL library.
|
||||||
|
*
|
||||||
|
* This API lets apps read input from video sources, like webcams. Camera
|
||||||
|
* devices can be enumerated, queried, and opened. Once opened, it will
|
||||||
|
* provide SDL_Surface objects as new frames of video come in. These surfaces
|
||||||
|
* can be uploaded to an SDL_Texture or processed as pixels in memory.
|
||||||
|
*
|
||||||
|
* Several platforms will alert the user if an app tries to access a camera,
|
||||||
|
* and some will present a UI asking the user if your application should be
|
||||||
|
* allowed to obtain images at all, which they can deny. A successfully opened
|
||||||
|
* camera will not provide images until permission is granted. Applications,
|
||||||
|
* after opening a camera device, can see if they were granted access by
|
||||||
|
* either polling with the SDL_GetCameraPermissionState() function, or waiting
|
||||||
|
* for an SDL_EVENT_CAMERA_DEVICE_APPROVED or SDL_EVENT_CAMERA_DEVICE_DENIED
|
||||||
|
* event. Platforms that don't have any user approval process will report
|
||||||
|
* approval immediately.
|
||||||
|
*
|
||||||
|
* Note that SDL cameras only provide video as individual frames; they will
|
||||||
|
* not provide full-motion video encoded in a movie file format, although an
|
||||||
|
* app is free to encode the acquired frames into any format it likes. It also
|
||||||
|
* does not provide audio from the camera hardware through this API; not only
|
||||||
|
* do many webcams not have microphones at all, many people--from streamers to
|
||||||
|
* people on Zoom calls--will want to use a separate microphone regardless of
|
||||||
|
* the camera. In any case, recorded audio will be available through SDL's
|
||||||
|
* audio API no matter what hardware provides the microphone.
|
||||||
|
*
|
||||||
|
* ## Camera gotchas
|
||||||
|
*
|
||||||
|
* Consumer-level camera hardware tends to take a little while to warm up,
|
||||||
|
* once the device has been opened. Generally most camera apps have some sort
|
||||||
|
* of UI to take a picture (a button to snap a pic while a preview is showing,
|
||||||
|
* some sort of multi-second countdown for the user to pose, like a photo
|
||||||
|
* booth), which puts control in the users' hands, or they are intended to
|
||||||
|
* stay on for long times (Pokemon Go, etc).
|
||||||
|
*
|
||||||
|
* It's not uncommon that a newly-opened camera will provide a couple of
|
||||||
|
* completely black frames, maybe followed by some under-exposed images. If
|
||||||
|
* taking a single frame automatically, or recording video from a camera's
|
||||||
|
* input without the user initiating it from a preview, it could be wise to
|
||||||
|
* drop the first several frames (if not the first several _seconds_ worth of
|
||||||
|
* frames!) before using images from a camera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_camera_h_
|
||||||
|
#define SDL_camera_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
#include <SDL3/SDL_error.h>
|
||||||
|
#include <SDL3/SDL_pixels.h>
|
||||||
|
#include <SDL3/SDL_properties.h>
|
||||||
|
#include <SDL3/SDL_surface.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a unique ID for a camera device for the time it is connected to the
|
||||||
|
* system, and is never reused for the lifetime of the application.
|
||||||
|
*
|
||||||
|
* If the device is disconnected and reconnected, it will get a new ID.
|
||||||
|
*
|
||||||
|
* The value 0 is an invalid ID.
|
||||||
|
*
|
||||||
|
* \since This datatype is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameras
|
||||||
|
*/
|
||||||
|
typedef Uint32 SDL_CameraID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The opaque structure used to identify an opened SDL camera.
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
typedef struct SDL_Camera SDL_Camera;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The details of an output format for a camera device.
|
||||||
|
*
|
||||||
|
* Cameras often support multiple formats; each one will be encapsulated in
|
||||||
|
* this struct.
|
||||||
|
*
|
||||||
|
* \since This struct is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameraSupportedFormats
|
||||||
|
* \sa SDL_GetCameraFormat
|
||||||
|
*/
|
||||||
|
typedef struct SDL_CameraSpec
|
||||||
|
{
|
||||||
|
SDL_PixelFormat format; /**< Frame format */
|
||||||
|
SDL_Colorspace colorspace; /**< Frame colorspace */
|
||||||
|
int width; /**< Frame width */
|
||||||
|
int height; /**< Frame height */
|
||||||
|
int framerate_numerator; /**< Frame rate numerator ((num / denom) == FPS, (denom / num) == duration in seconds) */
|
||||||
|
int framerate_denominator; /**< Frame rate demoninator ((num / denom) == FPS, (denom / num) == duration in seconds) */
|
||||||
|
} SDL_CameraSpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position of camera in relation to system device.
|
||||||
|
*
|
||||||
|
* \since This enum is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameraPosition
|
||||||
|
*/
|
||||||
|
typedef enum SDL_CameraPosition
|
||||||
|
{
|
||||||
|
SDL_CAMERA_POSITION_UNKNOWN,
|
||||||
|
SDL_CAMERA_POSITION_FRONT_FACING,
|
||||||
|
SDL_CAMERA_POSITION_BACK_FACING
|
||||||
|
} SDL_CameraPosition;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to get the number of built-in camera drivers.
|
||||||
|
*
|
||||||
|
* This function returns a hardcoded number. This never returns a negative
|
||||||
|
* value; if there are no drivers compiled into this build of SDL, this
|
||||||
|
* function returns zero. The presence of a driver in this list does not mean
|
||||||
|
* it will function, it just means SDL is capable of interacting with that
|
||||||
|
* interface. For example, a build of SDL might have v4l2 support, but if
|
||||||
|
* there's no kernel support available, SDL's v4l2 driver would fail if used.
|
||||||
|
*
|
||||||
|
* By default, SDL tries all drivers, in its preferred order, until one is
|
||||||
|
* found to be usable.
|
||||||
|
*
|
||||||
|
* \returns the number of built-in camera drivers.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameraDriver
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC int SDLCALL SDL_GetNumCameraDrivers(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to get the name of a built in camera driver.
|
||||||
|
*
|
||||||
|
* The list of camera drivers is given in the order that they are normally
|
||||||
|
* initialized by default; the drivers that seem more reasonable to choose
|
||||||
|
* first (as far as the SDL developers believe) are earlier in the list.
|
||||||
|
*
|
||||||
|
* The names of drivers are all simple, low-ASCII identifiers, like "v4l2",
|
||||||
|
* "coremedia" or "android". These never have Unicode characters, and are not
|
||||||
|
* meant to be proper names.
|
||||||
|
*
|
||||||
|
* \param index the index of the camera driver; the value ranges from 0 to
|
||||||
|
* SDL_GetNumCameraDrivers() - 1.
|
||||||
|
* \returns the name of the camera driver at the requested index, or NULL if
|
||||||
|
* an invalid index was specified.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetNumCameraDrivers
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC const char * SDLCALL SDL_GetCameraDriver(int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the current camera driver.
|
||||||
|
*
|
||||||
|
* The names of drivers are all simple, low-ASCII identifiers, like "v4l2",
|
||||||
|
* "coremedia" or "android". These never have Unicode characters, and are not
|
||||||
|
* meant to be proper names.
|
||||||
|
*
|
||||||
|
* \returns the name of the current camera driver or NULL if no driver has
|
||||||
|
* been initialized.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC const char * SDLCALL SDL_GetCurrentCameraDriver(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of currently connected camera devices.
|
||||||
|
*
|
||||||
|
* \param count a pointer filled in with the number of cameras returned, may
|
||||||
|
* be NULL.
|
||||||
|
* \returns a 0 terminated array of camera instance IDs or NULL on failure;
|
||||||
|
* call SDL_GetError() for more information. This should be freed
|
||||||
|
* with SDL_free() when it is no longer needed.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenCamera
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_CameraID * SDLCALL SDL_GetCameras(int *count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of native formats/sizes a camera supports.
|
||||||
|
*
|
||||||
|
* This returns a list of all formats and frame sizes that a specific camera
|
||||||
|
* can offer. This is useful if your app can accept a variety of image formats
|
||||||
|
* and sizes and so want to find the optimal spec that doesn't require
|
||||||
|
* conversion.
|
||||||
|
*
|
||||||
|
* This function isn't strictly required; if you call SDL_OpenCamera with a
|
||||||
|
* NULL spec, SDL will choose a native format for you, and if you instead
|
||||||
|
* specify a desired format, it will transparently convert to the requested
|
||||||
|
* format on your behalf.
|
||||||
|
*
|
||||||
|
* If `count` is not NULL, it will be filled with the number of elements in
|
||||||
|
* the returned array.
|
||||||
|
*
|
||||||
|
* Note that it's legal for a camera to supply an empty list. This is what
|
||||||
|
* will happen on Emscripten builds, since that platform won't tell _anything_
|
||||||
|
* about available cameras until you've opened one, and won't even tell if
|
||||||
|
* there _is_ a camera until the user has given you permission to check
|
||||||
|
* through a scary warning popup.
|
||||||
|
*
|
||||||
|
* \param instance_id the camera device instance ID.
|
||||||
|
* \param count a pointer filled in with the number of elements in the list,
|
||||||
|
* may be NULL.
|
||||||
|
* \returns a NULL terminated array of pointers to SDL_CameraSpec or NULL on
|
||||||
|
* failure; call SDL_GetError() for more information. This is a
|
||||||
|
* single allocation that should be freed with SDL_free() when it is
|
||||||
|
* no longer needed.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameras
|
||||||
|
* \sa SDL_OpenCamera
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_CameraSpec ** SDLCALL SDL_GetCameraSupportedFormats(SDL_CameraID instance_id, int *count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the human-readable device name for a camera.
|
||||||
|
*
|
||||||
|
* \param instance_id the camera device instance ID.
|
||||||
|
* \returns a human-readable device name or NULL on failure; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameras
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC const char * SDLCALL SDL_GetCameraName(SDL_CameraID instance_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the camera in relation to the system.
|
||||||
|
*
|
||||||
|
* Most platforms will report UNKNOWN, but mobile devices, like phones, can
|
||||||
|
* often make a distinction between cameras on the front of the device (that
|
||||||
|
* points towards the user, for taking "selfies") and cameras on the back (for
|
||||||
|
* filming in the direction the user is facing).
|
||||||
|
*
|
||||||
|
* \param instance_id the camera device instance ID.
|
||||||
|
* \returns the position of the camera on the system hardware.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameras
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_CameraPosition SDLCALL SDL_GetCameraPosition(SDL_CameraID instance_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a video recording device (a "camera").
|
||||||
|
*
|
||||||
|
* You can open the device with any reasonable spec, and if the hardware can't
|
||||||
|
* directly support it, it will convert data seamlessly to the requested
|
||||||
|
* format. This might incur overhead, including scaling of image data.
|
||||||
|
*
|
||||||
|
* If you would rather accept whatever format the device offers, you can pass
|
||||||
|
* a NULL spec here and it will choose one for you (and you can use
|
||||||
|
* SDL_Surface's conversion/scaling functions directly if necessary).
|
||||||
|
*
|
||||||
|
* You can call SDL_GetCameraFormat() to get the actual data format if passing
|
||||||
|
* a NULL spec here. You can see the exact specs a device can support without
|
||||||
|
* conversion with SDL_GetCameraSupportedFormats().
|
||||||
|
*
|
||||||
|
* SDL will not attempt to emulate framerate; it will try to set the hardware
|
||||||
|
* to the rate closest to the requested speed, but it won't attempt to limit
|
||||||
|
* or duplicate frames artificially; call SDL_GetCameraFormat() to see the
|
||||||
|
* actual framerate of the opened the device, and check your timestamps if
|
||||||
|
* this is crucial to your app!
|
||||||
|
*
|
||||||
|
* Note that the camera is not usable until the user approves its use! On some
|
||||||
|
* platforms, the operating system will prompt the user to permit access to
|
||||||
|
* the camera, and they can choose Yes or No at that point. Until they do, the
|
||||||
|
* camera will not be usable. The app should either wait for an
|
||||||
|
* SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event,
|
||||||
|
* or poll SDL_GetCameraPermissionState() occasionally until it returns
|
||||||
|
* non-zero. On platforms that don't require explicit user approval (and
|
||||||
|
* perhaps in places where the user previously permitted access), the approval
|
||||||
|
* event might come immediately, but it might come seconds, minutes, or hours
|
||||||
|
* later!
|
||||||
|
*
|
||||||
|
* \param instance_id the camera device instance ID.
|
||||||
|
* \param spec the desired format for data the device will provide. Can be
|
||||||
|
* NULL.
|
||||||
|
* \returns an SDL_Camera object or NULL on failure; call SDL_GetError() for
|
||||||
|
* more information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_GetCameras
|
||||||
|
* \sa SDL_GetCameraFormat
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_Camera * SDLCALL SDL_OpenCamera(SDL_CameraID instance_id, const SDL_CameraSpec *spec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query if camera access has been approved by the user.
|
||||||
|
*
|
||||||
|
* Cameras will not function between when the device is opened by the app and
|
||||||
|
* when the user permits access to the hardware. On some platforms, this
|
||||||
|
* presents as a popup dialog where the user has to explicitly approve access;
|
||||||
|
* on others the approval might be implicit and not alert the user at all.
|
||||||
|
*
|
||||||
|
* This function can be used to check the status of that approval. It will
|
||||||
|
* return 0 if still waiting for user response, 1 if the camera is approved
|
||||||
|
* for use, and -1 if the user denied access.
|
||||||
|
*
|
||||||
|
* Instead of polling with this function, you can wait for a
|
||||||
|
* SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event
|
||||||
|
* in the standard SDL event loop, which is guaranteed to be sent once when
|
||||||
|
* permission to use the camera is decided.
|
||||||
|
*
|
||||||
|
* If a camera is declined, there's nothing to be done but call
|
||||||
|
* SDL_CloseCamera() to dispose of it.
|
||||||
|
*
|
||||||
|
* \param camera the opened camera device to query.
|
||||||
|
* \returns -1 if user denied access to the camera, 1 if user approved access,
|
||||||
|
* 0 if no decision has been made yet.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenCamera
|
||||||
|
* \sa SDL_CloseCamera
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC int SDLCALL SDL_GetCameraPermissionState(SDL_Camera *camera);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the instance ID of an opened camera.
|
||||||
|
*
|
||||||
|
* \param camera an SDL_Camera to query.
|
||||||
|
* \returns the instance ID of the specified camera on success or 0 on
|
||||||
|
* failure; call SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenCamera
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_CameraID SDLCALL SDL_GetCameraID(SDL_Camera *camera);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the properties associated with an opened camera.
|
||||||
|
*
|
||||||
|
* \param camera the SDL_Camera obtained from SDL_OpenCamera().
|
||||||
|
* \returns a valid property ID on success or 0 on failure; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetCameraProperties(SDL_Camera *camera);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the spec that a camera is using when generating images.
|
||||||
|
*
|
||||||
|
* Note that this might not be the native format of the hardware, as SDL might
|
||||||
|
* be converting to this format behind the scenes.
|
||||||
|
*
|
||||||
|
* If the system is waiting for the user to approve access to the camera, as
|
||||||
|
* some platforms require, this will return false, but this isn't necessarily
|
||||||
|
* a fatal error; you should either wait for an
|
||||||
|
* SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event,
|
||||||
|
* or poll SDL_GetCameraPermissionState() occasionally until it returns
|
||||||
|
* non-zero.
|
||||||
|
*
|
||||||
|
* \param camera opened camera device.
|
||||||
|
* \param spec the SDL_CameraSpec to be initialized by this function.
|
||||||
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenCamera
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC bool SDLCALL SDL_GetCameraFormat(SDL_Camera *camera, SDL_CameraSpec *spec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acquire a frame.
|
||||||
|
*
|
||||||
|
* The frame is a memory pointer to the image data, whose size and format are
|
||||||
|
* given by the spec requested when opening the device.
|
||||||
|
*
|
||||||
|
* This is a non blocking API. If there is a frame available, a non-NULL
|
||||||
|
* surface is returned, and timestampNS will be filled with a non-zero value.
|
||||||
|
*
|
||||||
|
* Note that an error case can also return NULL, but a NULL by itself is
|
||||||
|
* normal and just signifies that a new frame is not yet available. Note that
|
||||||
|
* even if a camera device fails outright (a USB camera is unplugged while in
|
||||||
|
* use, etc), SDL will send an event separately to notify the app, but
|
||||||
|
* continue to provide blank frames at ongoing intervals until
|
||||||
|
* SDL_CloseCamera() is called, so real failure here is almost always an out
|
||||||
|
* of memory condition.
|
||||||
|
*
|
||||||
|
* After use, the frame should be released with SDL_ReleaseCameraFrame(). If
|
||||||
|
* you don't do this, the system may stop providing more video!
|
||||||
|
*
|
||||||
|
* Do not call SDL_DestroySurface() on the returned surface! It must be given
|
||||||
|
* back to the camera subsystem with SDL_ReleaseCameraFrame!
|
||||||
|
*
|
||||||
|
* If the system is waiting for the user to approve access to the camera, as
|
||||||
|
* some platforms require, this will return NULL (no frames available); you
|
||||||
|
* should either wait for an SDL_EVENT_CAMERA_DEVICE_APPROVED (or
|
||||||
|
* SDL_EVENT_CAMERA_DEVICE_DENIED) event, or poll
|
||||||
|
* SDL_GetCameraPermissionState() occasionally until it returns non-zero.
|
||||||
|
*
|
||||||
|
* \param camera opened camera device.
|
||||||
|
* \param timestampNS a pointer filled in with the frame's timestamp, or 0 on
|
||||||
|
* error. Can be NULL.
|
||||||
|
* \returns a new frame of video on success, NULL if none is currently
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_ReleaseCameraFrame
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_AcquireCameraFrame(SDL_Camera *camera, Uint64 *timestampNS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a frame of video acquired from a camera.
|
||||||
|
*
|
||||||
|
* Let the back-end re-use the internal buffer for camera.
|
||||||
|
*
|
||||||
|
* This function _must_ be called only on surface objects returned by
|
||||||
|
* SDL_AcquireCameraFrame(). This function should be called as quickly as
|
||||||
|
* possible after acquisition, as SDL keeps a small FIFO queue of surfaces for
|
||||||
|
* video frames; if surfaces aren't released in a timely manner, SDL may drop
|
||||||
|
* upcoming video frames from the camera.
|
||||||
|
*
|
||||||
|
* If the app needs to keep the surface for a significant time, they should
|
||||||
|
* make a copy of it and release the original.
|
||||||
|
*
|
||||||
|
* The app should not use the surface again after calling this function;
|
||||||
|
* assume the surface is freed and the pointer is invalid.
|
||||||
|
*
|
||||||
|
* \param camera opened camera device.
|
||||||
|
* \param frame the video frame surface to release.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_AcquireCameraFrame
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_ReleaseCameraFrame(SDL_Camera *camera, SDL_Surface *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to shut down camera processing and close the camera
|
||||||
|
* device.
|
||||||
|
*
|
||||||
|
* \param camera opened camera device.
|
||||||
|
*
|
||||||
|
* \threadsafety It is safe to call this function from any thread, but no
|
||||||
|
* thread may reference `device` once this function is called.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenCamera
|
||||||
|
*/
|
||||||
|
extern SDL_DECLSPEC void SDLCALL SDL_CloseCamera(SDL_Camera *camera);
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <SDL3/SDL_close_code.h>
|
||||||
|
|
||||||
|
#endif /* SDL_camera_h_ */
|
||||||