koffi 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.md +6 -0
- package/build/qemu/2.1.2/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.2/koffi_win32_x64.tar.gz +0 -0
- package/doc/templates/badges.html +3 -0
- package/package.json +2 -2
- package/src/abi_arm64.cc +35 -1
- package/src/abi_x64_win.cc +2 -8
- package/src/abi_x86.cc +1 -7
- package/src/ffi.hh +1 -1
- package/src/util.hh +6 -0
- package/test/raylib.js +37 -5
- package/vendor/libcc/libcc.cc +430 -196
- package/vendor/libcc/libcc.hh +1417 -1283
- package/vendor/raylib/BINDINGS.md +87 -70
- package/vendor/raylib/CHANGELOG +263 -50
- package/vendor/raylib/CMakeLists.txt +12 -0
- package/vendor/raylib/CMakeOptions.txt +8 -1
- package/vendor/raylib/CONVENTIONS.md +2 -3
- package/vendor/raylib/FAQ.md +137 -0
- package/vendor/raylib/HISTORY.md +62 -29
- package/vendor/raylib/LICENSE +1 -1
- package/vendor/raylib/README.md +22 -17
- package/vendor/raylib/ROADMAP.md +8 -7
- package/vendor/raylib/cmake/CompileDefinitions.cmake +19 -15
- package/vendor/raylib/cmake/GlfwImport.cmake +2 -0
- package/vendor/raylib/cmake/LibraryConfigurations.cmake +22 -16
- package/vendor/raylib/cmake/raylib-config.cmake +52 -49
- package/vendor/raylib/examples/CMakeLists.txt +14 -9
- package/vendor/raylib/examples/Makefile +112 -125
- package/vendor/raylib/examples/Makefile.Android +1 -1
- package/vendor/raylib/examples/Makefile.Web +145 -158
- package/vendor/raylib/examples/README.md +141 -141
- package/vendor/raylib/examples/audio/audio_module_playing.c +9 -4
- package/vendor/raylib/examples/audio/audio_multichannel_sound.c +8 -3
- package/vendor/raylib/examples/audio/audio_music_stream.c +16 -11
- package/vendor/raylib/examples/audio/audio_raw_stream.c +57 -9
- package/vendor/raylib/examples/audio/audio_sound_loading.c +8 -3
- package/vendor/raylib/examples/audio/audio_stream_effects.c +179 -0
- package/vendor/raylib/examples/audio/audio_stream_effects.png +0 -0
- package/vendor/raylib/examples/build.zig +17 -6
- package/vendor/raylib/examples/core/core_2d_camera.c +8 -4
- package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.c +105 -0
- package/vendor/raylib/examples/core/core_2d_camera_mouse_zoom.png +0 -0
- package/vendor/raylib/examples/core/core_2d_camera_platformer.c +11 -6
- package/vendor/raylib/examples/core/core_3d_camera_first_person.c +9 -4
- package/vendor/raylib/examples/core/core_3d_camera_free.c +9 -4
- package/vendor/raylib/examples/core/core_3d_camera_mode.c +8 -3
- package/vendor/raylib/examples/core/core_3d_picking.c +9 -4
- package/vendor/raylib/examples/core/core_basic_screen_manager.c +9 -7
- package/vendor/raylib/examples/core/core_basic_window.c +8 -3
- package/vendor/raylib/examples/core/core_basic_window_web.c +13 -11
- package/vendor/raylib/examples/core/core_custom_frame_control.c +9 -4
- package/vendor/raylib/examples/core/core_custom_logging.c +12 -8
- package/vendor/raylib/examples/core/core_drop_files.c +20 -12
- package/vendor/raylib/examples/core/core_input_gamepad.c +20 -15
- package/vendor/raylib/examples/core/core_input_gestures.c +19 -15
- package/vendor/raylib/examples/core/core_input_keys.c +8 -3
- package/vendor/raylib/examples/core/core_input_mouse.c +8 -3
- package/vendor/raylib/examples/core/core_input_mouse_wheel.c +8 -3
- package/vendor/raylib/examples/core/core_input_multitouch.c +8 -3
- package/vendor/raylib/examples/core/core_loading_thread.c +10 -6
- package/vendor/raylib/examples/core/core_random_values.c +8 -3
- package/vendor/raylib/examples/core/core_scissor_test.c +8 -3
- package/vendor/raylib/examples/core/core_smooth_pixelperfect.c +9 -4
- package/vendor/raylib/examples/core/core_split_screen.c +8 -3
- package/vendor/raylib/examples/core/core_storage_values.c +109 -3
- package/vendor/raylib/examples/core/core_vr_simulator.c +15 -7
- package/vendor/raylib/examples/core/core_window_flags.c +8 -3
- package/vendor/raylib/examples/core/core_window_letterbox.c +13 -18
- package/vendor/raylib/examples/core/core_window_should_close.c +77 -0
- package/vendor/raylib/examples/core/core_window_should_close.png +0 -0
- package/vendor/raylib/examples/core/core_world_screen.c +9 -4
- package/vendor/raylib/examples/examples_template.c +8 -3
- package/vendor/raylib/examples/models/models_animation.c +11 -7
- package/vendor/raylib/examples/models/models_billboard.c +9 -4
- package/vendor/raylib/examples/models/models_box_collisions.c +8 -3
- package/vendor/raylib/examples/models/models_cubicmap.c +9 -4
- package/vendor/raylib/examples/models/models_first_person_maze.c +9 -4
- package/vendor/raylib/examples/models/models_geometric_shapes.c +8 -3
- package/vendor/raylib/examples/models/models_heightmap.c +9 -4
- package/vendor/raylib/examples/models/models_loading.c +21 -17
- package/vendor/raylib/examples/models/models_loading_gltf.c +15 -41
- package/vendor/raylib/examples/models/models_loading_vox.c +9 -4
- package/vendor/raylib/examples/models/models_mesh_generation.c +71 -58
- package/vendor/raylib/examples/models/models_mesh_picking.c +25 -7
- package/vendor/raylib/examples/models/models_orthographic_projection.c +8 -5
- package/vendor/raylib/examples/models/models_rlgl_solar_system.c +6 -4
- package/vendor/raylib/examples/models/models_skybox.c +16 -12
- package/vendor/raylib/examples/models/models_waving_cubes.c +9 -4
- package/vendor/raylib/examples/models/models_yaw_pitch_roll.c +12 -7
- package/vendor/raylib/examples/models/resources/LICENSE.md +9 -10
- package/vendor/raylib/examples/models/resources/models/gltf/LICENSE +2 -23
- package/vendor/raylib/examples/models/resources/models/gltf/{raylib_32x32.glb → raylib_logo_3d.glb} +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/robot.blend +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/robot.glb +0 -0
- package/vendor/raylib/examples/others/easings_testbed.c +10 -8
- package/vendor/raylib/examples/others/easings_testbed.png +0 -0
- package/vendor/raylib/examples/others/embedded_files_loading.c +10 -5
- package/vendor/raylib/examples/others/embedded_files_loading.png +0 -0
- package/vendor/raylib/examples/others/raylib_opengl_interop.c +10 -6
- package/vendor/raylib/{src/extras/easings.h → examples/others/reasings.h} +38 -38
- package/vendor/raylib/examples/others/rlgl_compute_shader.c +21 -20
- package/vendor/raylib/examples/others/rlgl_compute_shader.png +0 -0
- package/vendor/raylib/examples/others/rlgl_standalone.c +4 -4
- package/vendor/raylib/examples/others/rlgl_standalone.png +0 -0
- package/vendor/raylib/examples/raylib_compile_execute.bat +2 -2
- package/vendor/raylib/examples/shaders/resources/shaders/glsl330/lighting.fs +1 -1
- package/vendor/raylib/examples/shaders/resources/shaders/glsl330/{base_lighting_instanced.vs → lighting_instancing.vs} +2 -2
- package/vendor/raylib/examples/shaders/rlights.h +14 -27
- package/vendor/raylib/examples/shaders/shaders_basic_lighting.c +24 -26
- package/vendor/raylib/examples/shaders/shaders_custom_uniform.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_eratosthenes.c +13 -8
- package/vendor/raylib/examples/shaders/shaders_fog.c +8 -12
- package/vendor/raylib/examples/shaders/shaders_hot_reloading.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_julia_set.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_mesh_instancing.c +45 -119
- package/vendor/raylib/examples/shaders/shaders_model_shader.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_multi_sample2d.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_palette_switch.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_postprocessing.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_raymarching.c +14 -11
- package/vendor/raylib/examples/shaders/shaders_shapes_textures.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_simple_mask.c +10 -5
- package/vendor/raylib/examples/shaders/shaders_spotlight.c +10 -6
- package/vendor/raylib/examples/shaders/shaders_texture_drawing.c +9 -4
- package/vendor/raylib/examples/shaders/shaders_texture_outline.c +8 -3
- package/vendor/raylib/examples/shaders/shaders_texture_waves.c +8 -3
- package/vendor/raylib/{src/extras → examples/shapes}/raygui.h +1290 -1141
- package/vendor/raylib/examples/{others/easings.h → shapes/reasings.h} +40 -40
- package/vendor/raylib/examples/shapes/shapes_basic_shapes.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_bouncing_ball.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_collision_area.c +10 -4
- package/vendor/raylib/examples/shapes/shapes_colors_palette.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_draw_circle_sector.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_draw_rectangle_rounded.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_draw_ring.c +10 -6
- package/vendor/raylib/examples/shapes/shapes_easings_ball_anim.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_easings_box_anim.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_easings_rectangle_array.c +9 -4
- package/vendor/raylib/examples/shapes/shapes_following_eyes.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_lines_bezier.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_logo_raylib.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_logo_raylib_anim.c +8 -3
- package/vendor/raylib/examples/shapes/shapes_rectangle_scaling.c +14 -5
- package/vendor/raylib/examples/shapes/shapes_top_down_lights.c +355 -0
- package/vendor/raylib/examples/shapes/shapes_top_down_lights.png +0 -0
- package/vendor/raylib/examples/text/resources/DotGothic16-Regular.ttf +0 -0
- package/vendor/raylib/examples/text/resources/DotGothic16-Regular_OFL.txt +93 -0
- package/vendor/raylib/examples/text/resources/LICENSE.md +1 -1
- package/vendor/raylib/examples/text/text_codepoints_loading.c +138 -0
- package/vendor/raylib/examples/text/text_codepoints_loading.png +0 -0
- package/vendor/raylib/examples/text/text_draw_3d.c +42 -33
- package/vendor/raylib/examples/text/text_font_filters.c +14 -11
- package/vendor/raylib/examples/text/text_font_loading.c +9 -4
- package/vendor/raylib/examples/text/text_font_sdf.c +9 -4
- package/vendor/raylib/examples/text/text_font_spritefont.c +12 -6
- package/vendor/raylib/examples/text/text_format_text.c +8 -3
- package/vendor/raylib/examples/text/text_input_box.c +8 -3
- package/vendor/raylib/examples/text/text_raylib_fonts.c +9 -4
- package/vendor/raylib/examples/text/text_rectangle_bounds.c +9 -5
- package/vendor/raylib/examples/text/text_unicode.c +9 -7
- package/vendor/raylib/examples/text/text_writing_anim.c +8 -3
- package/vendor/raylib/examples/textures/resources/scarfy_run.gif +0 -0
- package/vendor/raylib/examples/textures/textures_background_scrolling.c +8 -3
- package/vendor/raylib/examples/textures/textures_blend_modes.c +8 -3
- package/vendor/raylib/examples/textures/textures_bunnymark.c +8 -3
- package/vendor/raylib/examples/textures/textures_draw_tiled.c +14 -10
- package/vendor/raylib/examples/textures/textures_fog_of_war.c +154 -0
- package/vendor/raylib/examples/textures/textures_fog_of_war.png +0 -0
- package/vendor/raylib/examples/textures/textures_gif_player.c +121 -0
- package/vendor/raylib/examples/textures/textures_gif_player.png +0 -0
- package/vendor/raylib/examples/textures/textures_image_drawing.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_generation.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_loading.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_processing.c +8 -3
- package/vendor/raylib/examples/textures/textures_image_text.c +8 -3
- package/vendor/raylib/examples/textures/textures_logo_raylib.c +8 -3
- package/vendor/raylib/examples/textures/textures_mouse_painting.c +9 -4
- package/vendor/raylib/examples/textures/textures_npatch_drawing.c +8 -3
- package/vendor/raylib/examples/textures/textures_particles_blending.c +8 -3
- package/vendor/raylib/examples/textures/textures_polygon.c +9 -5
- package/vendor/raylib/examples/textures/textures_raw_data.c +8 -3
- package/vendor/raylib/examples/textures/{textures_rectangle.c → textures_sprite_anim.c} +11 -5
- package/vendor/raylib/examples/textures/{textures_rectangle.png → textures_sprite_anim.png} +0 -0
- package/vendor/raylib/examples/textures/textures_sprite_button.c +8 -3
- package/vendor/raylib/examples/textures/textures_sprite_explosion.c +8 -3
- package/vendor/raylib/examples/textures/textures_srcrec_dstrec.c +8 -3
- package/vendor/raylib/examples/textures/textures_to_image.c +8 -3
- package/vendor/raylib/parser/LICENSE +1 -1
- package/vendor/raylib/parser/Makefile +28 -0
- package/vendor/raylib/parser/README.md +49 -5
- package/vendor/raylib/parser/output/raylib_api.json +10717 -0
- package/vendor/raylib/parser/output/raylib_api.lua +7435 -0
- package/vendor/raylib/parser/{raylib_api.txt → output/raylib_api.txt} +1371 -824
- package/vendor/raylib/parser/{raylib_api.xml → output/raylib_api.xml} +827 -595
- package/vendor/raylib/parser/raylib_parser.c +1174 -196
- package/vendor/raylib/projects/4coder/Makefile +2 -4
- package/vendor/raylib/projects/4coder/main.c +0 -1
- package/vendor/raylib/projects/CMake/CMakeLists.txt +13 -16
- package/vendor/raylib/projects/CMake/README.md +27 -0
- package/vendor/raylib/projects/CMake/core_basic_window.c +52 -31
- package/vendor/raylib/projects/CodeBlocks/README.md +4 -4
- package/vendor/raylib/projects/Geany/core_basic_window.c +1 -1
- package/vendor/raylib/projects/Notepad++/c_raylib.xml +168 -128
- package/vendor/raylib/projects/Notepad++/npes_saved_tcc.txt +0 -0
- package/vendor/raylib/projects/Notepad++/npes_saved_w64devkit.txt +0 -0
- package/vendor/raylib/projects/Notepad++/npes_saved_zig.txt +0 -0
- package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +168 -84
- package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +67 -51
- package/vendor/raylib/projects/README.md +1 -1
- package/vendor/raylib/projects/VSCode/.vscode/c_cpp_properties.json +1 -1
- package/vendor/raylib/projects/VSCode/Makefile +8 -11
- package/vendor/raylib/projects/VSCode/main.c +53 -26
- package/vendor/raylib/projects/VSCode/resources/LICENSE +1 -0
- package/vendor/raylib/projects/scripts/build-linux.sh +6 -6
- package/vendor/raylib/projects/scripts/build-osx.sh +6 -6
- package/vendor/raylib/projects/scripts/build-rpi.sh +6 -6
- package/vendor/raylib/projects/scripts/build-windows.bat +2 -2
- package/vendor/raylib/src/CMakeLists.txt +6 -7
- package/vendor/raylib/src/Makefile +209 -103
- package/vendor/raylib/src/build.zig +56 -20
- package/vendor/raylib/src/config.h +32 -27
- package/vendor/raylib/src/external/cgltf.h +342 -104
- package/vendor/raylib/src/external/dr_wav.h +487 -225
- package/vendor/raylib/src/external/glfw/src/posix_time.c +1 -3
- package/vendor/raylib/src/external/glfw/src/wl_init.c +1 -3
- package/vendor/raylib/src/external/jar_xm.h +2 -1
- package/vendor/raylib/src/external/miniaudio.h +62251 -42061
- package/vendor/raylib/src/external/qoi.h +671 -0
- package/vendor/raylib/src/external/stb_vorbis.h +1 -1
- package/vendor/raylib/src/external/vox_loader.h +30 -25
- package/vendor/raylib/src/minshell.html +82 -0
- package/vendor/raylib/src/raudio.c +359 -201
- package/vendor/raylib/src/raylib.dll.rc +5 -5
- package/vendor/raylib/src/raylib.dll.rc.data +0 -0
- package/vendor/raylib/src/raylib.h +95 -63
- package/vendor/raylib/src/raylib.rc +5 -5
- package/vendor/raylib/src/raylib.rc.data +0 -0
- package/vendor/raylib/src/raymath.h +391 -133
- package/vendor/raylib/src/rcamera.h +32 -41
- package/vendor/raylib/src/rcore.c +775 -471
- package/vendor/raylib/src/rgestures.h +5 -5
- package/vendor/raylib/src/rglfw.c +3 -3
- package/vendor/raylib/src/rlgl.h +184 -144
- package/vendor/raylib/src/rmodels.c +207 -144
- package/vendor/raylib/src/rshapes.c +105 -47
- package/vendor/raylib/src/rtext.c +255 -38
- package/vendor/raylib/src/rtextures.c +167 -71
- package/vendor/raylib/src/shell.html +63 -63
- package/vendor/raylib/src/utils.c +49 -3
- package/vendor/raylib/src/utils.h +3 -3
- package/build/qemu/2.1.1/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.1/koffi_win32_x64.tar.gz +0 -0
- package/vendor/raylib/CONTRIBUTORS.md +0 -63
- package/vendor/raylib/SPONSORS.md +0 -68
- package/vendor/raylib/examples/core/core_quat_conversion.c +0 -132
- package/vendor/raylib/examples/core/core_quat_conversion.png +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/AnimatedMorphCube.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/AnimatedTriangle.gltf +0 -118
- package/vendor/raylib/examples/models/resources/models/gltf/BoxAnimated.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/girl.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/rigged_figure.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/gltf/vertex_colored_object.glb +0 -0
- package/vendor/raylib/examples/models/resources/models/iqm/vertex_colored_object.iqm +0 -0
- package/vendor/raylib/examples/models/rlights.h +0 -183
- package/vendor/raylib/examples/others/raudio_standalone.c +0 -152
- package/vendor/raylib/examples/others/resources/audio/country.mp3 +0 -0
- package/vendor/raylib/examples/others/resources/audio/target.ogg +0 -0
- package/vendor/raylib/examples/others/resources/audio/weird.wav +0 -0
- package/vendor/raylib/examples/physics/physics_demo.c +0 -128
- package/vendor/raylib/examples/physics/physics_demo.png +0 -0
- package/vendor/raylib/examples/physics/physics_friction.c +0 -142
- package/vendor/raylib/examples/physics/physics_friction.png +0 -0
- package/vendor/raylib/examples/physics/physics_movement.c +0 -128
- package/vendor/raylib/examples/physics/physics_movement.png +0 -0
- package/vendor/raylib/examples/physics/physics_restitution.c +0 -129
- package/vendor/raylib/examples/physics/physics_restitution.png +0 -0
- package/vendor/raylib/examples/physics/physics_shatter.c +0 -111
- package/vendor/raylib/examples/physics/physics_shatter.png +0 -0
- package/vendor/raylib/parser/raylib_api.json +0 -6668
- package/vendor/raylib/projects/VS2019/raylib/raylib.rc +0 -0
- package/vendor/raylib/projects/VS2019/raylib/resource.h +0 -14
- package/vendor/raylib/src/extras/physac.h +0 -1977
- package/vendor/raylib/src/extras/rmem.h +0 -751
- package/vendor/raylib/src/raudio.h +0 -198
|
@@ -22,9 +22,11 @@
|
|
|
22
22
|
* Windowing and input system configured for Android device, app activity managed internally in this module.
|
|
23
23
|
* NOTE: OpenGL ES 2.0 is required and graphic device is managed by EGL
|
|
24
24
|
*
|
|
25
|
-
* #define PLATFORM_RPI
|
|
25
|
+
* #define PLATFORM_RPI (deprecated - RPI OS Buster only)
|
|
26
26
|
* Windowing and input system configured for Raspberry Pi in native mode (no XWindow required),
|
|
27
27
|
* graphic device is managed by EGL and inputs are processed is raw mode, reading from /dev/input/
|
|
28
|
+
* WARNING: This platform is deprecated, since RPI OS Bullseye, the old Dispmanx libraries are not
|
|
29
|
+
* supported and you must be using PLATFORM_DRM
|
|
28
30
|
*
|
|
29
31
|
* #define PLATFORM_DRM
|
|
30
32
|
* Windowing and input system configured for DRM native mode (RPI4 and other devices)
|
|
@@ -55,9 +57,6 @@
|
|
|
55
57
|
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other running processes or
|
|
56
58
|
* blocking the device if not restored properly. Use with care.
|
|
57
59
|
*
|
|
58
|
-
* #define SUPPORT_MOUSE_CURSOR_POINT
|
|
59
|
-
* Draw a mouse pointer on screen
|
|
60
|
-
*
|
|
61
60
|
* #define SUPPORT_BUSY_WAIT_LOOP
|
|
62
61
|
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
|
|
63
62
|
*
|
|
@@ -78,9 +77,6 @@
|
|
|
78
77
|
* provided by stb_image and stb_image_write libraries, so, those libraries must be enabled on textures module
|
|
79
78
|
* for linkage
|
|
80
79
|
*
|
|
81
|
-
* #define SUPPORT_DATA_STORAGE
|
|
82
|
-
* Support saving binary data automatically to a generated storage.data file. This file is managed internally
|
|
83
|
-
*
|
|
84
80
|
* #define SUPPORT_EVENTS_AUTOMATION
|
|
85
81
|
* Support automatic generated events, loading and recording of those events when required
|
|
86
82
|
*
|
|
@@ -93,7 +89,7 @@
|
|
|
93
89
|
*
|
|
94
90
|
* LICENSE: zlib/libpng
|
|
95
91
|
*
|
|
96
|
-
* Copyright (c) 2013-
|
|
92
|
+
* Copyright (c) 2013-2022 Ramon Santamaria (@raysan5)
|
|
97
93
|
*
|
|
98
94
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
|
99
95
|
* will the authors be held liable for any damages arising from the use of this software.
|
|
@@ -160,21 +156,43 @@
|
|
|
160
156
|
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
|
|
161
157
|
#endif
|
|
162
158
|
|
|
159
|
+
// Platform specific defines to handle GetApplicationDirectory()
|
|
160
|
+
#if defined (PLATFORM_DESKTOP)
|
|
161
|
+
#if defined(_WIN32)
|
|
162
|
+
#ifndef MAX_PATH
|
|
163
|
+
#define MAX_PATH 1025
|
|
164
|
+
#endif
|
|
165
|
+
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void *hModule, void *lpFilename, unsigned long nSize);
|
|
166
|
+
__declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(void *hModule, void *lpFilename, unsigned long nSize);
|
|
167
|
+
__declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, void *widestr, int cchwide, void *str, int cbmb, void *defchar, int *used_default);
|
|
168
|
+
#elif defined(__linux__)
|
|
169
|
+
#include <unistd.h>
|
|
170
|
+
#elif defined(__APPLE__)
|
|
171
|
+
#include <sys/syslimits.h>
|
|
172
|
+
#include <mach-o/dyld.h>
|
|
173
|
+
#endif // OSs
|
|
174
|
+
#endif // PLATFORM_DESKTOP
|
|
175
|
+
|
|
163
176
|
#include <stdlib.h> // Required for: srand(), rand(), atexit()
|
|
164
177
|
#include <stdio.h> // Required for: sprintf() [Used in OpenURL()]
|
|
165
|
-
#include <string.h> // Required for: strrchr(), strcmp(), strlen()
|
|
178
|
+
#include <string.h> // Required for: strrchr(), strcmp(), strlen(), memset()
|
|
166
179
|
#include <time.h> // Required for: time() [Used in InitTimer()]
|
|
167
180
|
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
|
|
168
181
|
|
|
169
|
-
#
|
|
182
|
+
#define _CRT_INTERNAL_NONSTDC_NAMES 1
|
|
183
|
+
#include <sys/stat.h> // Required for: stat(), S_ISREG [Used in GetFileModTime(), IsFilePath()]
|
|
184
|
+
|
|
185
|
+
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
|
|
186
|
+
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
|
187
|
+
#endif
|
|
170
188
|
|
|
171
189
|
#if defined(PLATFORM_DESKTOP) && defined(_WIN32) && (defined(_MSC_VER) || defined(__TINYC__))
|
|
172
190
|
#define DIRENT_MALLOC RL_MALLOC
|
|
173
191
|
#define DIRENT_FREE RL_FREE
|
|
174
192
|
|
|
175
|
-
#include "external/dirent.h" // Required for: DIR, opendir(), closedir() [Used in
|
|
193
|
+
#include "external/dirent.h" // Required for: DIR, opendir(), closedir() [Used in LoadDirectoryFiles()]
|
|
176
194
|
#else
|
|
177
|
-
#include <dirent.h> // Required for: DIR, opendir(), closedir() [Used in
|
|
195
|
+
#include <dirent.h> // Required for: DIR, opendir(), closedir() [Used in LoadDirectoryFiles()]
|
|
178
196
|
#endif
|
|
179
197
|
|
|
180
198
|
#if defined(_WIN32)
|
|
@@ -205,7 +223,7 @@
|
|
|
205
223
|
unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
|
|
206
224
|
#endif
|
|
207
225
|
#endif
|
|
208
|
-
#if defined(__linux__) || defined(__FreeBSD__)
|
|
226
|
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
209
227
|
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
|
|
210
228
|
|
|
211
229
|
//#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type
|
|
@@ -225,6 +243,7 @@
|
|
|
225
243
|
//#include <android/sensor.h> // Required for: Android sensors functions (accelerometer, gyroscope, light...)
|
|
226
244
|
#include <android/window.h> // Required for: AWINDOW_FLAG_FULLSCREEN definition and others
|
|
227
245
|
#include <android_native_app_glue.h> // Required for: android_app struct and activity management
|
|
246
|
+
#include <jni.h> // Required for: JNIEnv and JavaVM [Used in OpenURL()]
|
|
228
247
|
|
|
229
248
|
#include <EGL/egl.h> // Native platform windowing system interface
|
|
230
249
|
//#include <GLES2/gl2.h> // OpenGL ES 2.0 library (not required in this module, only in rlgl)
|
|
@@ -275,12 +294,11 @@
|
|
|
275
294
|
#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
|
276
295
|
#endif
|
|
277
296
|
|
|
297
|
+
#ifndef MAX_FILEPATH_CAPACITY
|
|
298
|
+
#define MAX_FILEPATH_CAPACITY 8192 // Maximum capacity for filepath
|
|
299
|
+
#endif
|
|
278
300
|
#ifndef MAX_FILEPATH_LENGTH
|
|
279
|
-
#
|
|
280
|
-
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
|
|
281
|
-
#else
|
|
282
|
-
#define MAX_FILEPATH_LENGTH 512 // Maximum length supported for filepaths
|
|
283
|
-
#endif
|
|
301
|
+
#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
|
|
284
302
|
#endif
|
|
285
303
|
|
|
286
304
|
#ifndef MAX_KEYBOARD_KEYS
|
|
@@ -308,12 +326,6 @@
|
|
|
308
326
|
#define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue
|
|
309
327
|
#endif
|
|
310
328
|
|
|
311
|
-
#if defined(SUPPORT_DATA_STORAGE)
|
|
312
|
-
#ifndef STORAGE_DATA_FILE
|
|
313
|
-
#define STORAGE_DATA_FILE "storage.data" // Automatic storage filename
|
|
314
|
-
#endif
|
|
315
|
-
#endif
|
|
316
|
-
|
|
317
329
|
#ifndef MAX_DECOMPRESSION_SIZE
|
|
318
330
|
#define MAX_DECOMPRESSION_SIZE 64 // Maximum size allocated for decompression in MB
|
|
319
331
|
#endif
|
|
@@ -376,6 +388,7 @@ typedef struct CoreData {
|
|
|
376
388
|
bool fullscreen; // Check if fullscreen mode is enabled
|
|
377
389
|
bool shouldClose; // Check if window set for closing
|
|
378
390
|
bool resizedLastFrame; // Check if window has been resized last frame
|
|
391
|
+
bool eventWaiting; // Wait for events before ending frame
|
|
379
392
|
|
|
380
393
|
Point position; // Window position on screen (required on fullscreen toggle)
|
|
381
394
|
Size display; // Display width and height (monitor, device-screen, LCD, ...)
|
|
@@ -385,8 +398,8 @@ typedef struct CoreData {
|
|
|
385
398
|
Point renderOffset; // Offset from render area (must be divided by 2)
|
|
386
399
|
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
|
|
387
400
|
|
|
388
|
-
char **
|
|
389
|
-
int dropFileCount;
|
|
401
|
+
char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
|
|
402
|
+
unsigned int dropFileCount; // Count dropped files strings
|
|
390
403
|
|
|
391
404
|
} Window;
|
|
392
405
|
#if defined(PLATFORM_ANDROID)
|
|
@@ -437,8 +450,8 @@ typedef struct CoreData {
|
|
|
437
450
|
|
|
438
451
|
char currentButtonState[MAX_MOUSE_BUTTONS]; // Registers current mouse button state
|
|
439
452
|
char previousButtonState[MAX_MOUSE_BUTTONS]; // Registers previous mouse button state
|
|
440
|
-
|
|
441
|
-
|
|
453
|
+
Vector2 currentWheelMove; // Registers current mouse wheel variation
|
|
454
|
+
Vector2 previousWheelMove; // Registers previous mouse wheel variation
|
|
442
455
|
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
|
443
456
|
// NOTE: currentButtonState[] can't be written directly due to multithreading, app could miss the update
|
|
444
457
|
char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab
|
|
@@ -482,17 +495,16 @@ typedef struct CoreData {
|
|
|
482
495
|
//----------------------------------------------------------------------------------
|
|
483
496
|
// Global Variables Definition
|
|
484
497
|
//----------------------------------------------------------------------------------
|
|
485
|
-
|
|
498
|
+
const char *raylibVersion = RAYLIB_VERSION; // raylib version symbol, it could be required for some bindings
|
|
486
499
|
|
|
487
|
-
static
|
|
488
|
-
static int dirFileCount = 0; // Count directory files strings
|
|
500
|
+
static CoreData CORE = { 0 }; // Global CORE state context
|
|
489
501
|
|
|
490
502
|
#if defined(SUPPORT_SCREEN_CAPTURE)
|
|
491
503
|
static int screenshotCounter = 0; // Screenshots counter
|
|
492
504
|
#endif
|
|
493
505
|
|
|
494
506
|
#if defined(SUPPORT_GIF_RECORDING)
|
|
495
|
-
static int gifFrameCounter = 0;
|
|
507
|
+
static int gifFrameCounter = 0; // GIF frames counter
|
|
496
508
|
static bool gifRecording = false; // GIF recording state
|
|
497
509
|
static MsfGifState gifState = { 0 }; // MSGIF context state
|
|
498
510
|
#endif
|
|
@@ -510,7 +522,7 @@ typedef enum AutomationEventType {
|
|
|
510
522
|
INPUT_MOUSE_BUTTON_UP, // param[0]: button
|
|
511
523
|
INPUT_MOUSE_BUTTON_DOWN, // param[0]: button
|
|
512
524
|
INPUT_MOUSE_POSITION, // param[0]: x, param[1]: y
|
|
513
|
-
INPUT_MOUSE_WHEEL_MOTION, // param[0]: delta
|
|
525
|
+
INPUT_MOUSE_WHEEL_MOTION, // param[0]: x delta, param[1]: y delta
|
|
514
526
|
INPUT_GAMEPAD_CONNECT, // param[0]: gamepad
|
|
515
527
|
INPUT_GAMEPAD_DISCONNECT, // param[0]: gamepad
|
|
516
528
|
INPUT_GAMEPAD_BUTTON_UP, // param[0]: button
|
|
@@ -588,7 +600,7 @@ static bool eventsRecording = false; // Record events
|
|
|
588
600
|
//----------------------------------------------------------------------------------
|
|
589
601
|
// Other Modules Functions Declaration (required by core)
|
|
590
602
|
//----------------------------------------------------------------------------------
|
|
591
|
-
#if defined(SUPPORT_DEFAULT_FONT)
|
|
603
|
+
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
592
604
|
extern void LoadFontDefault(void); // [Module: text] Loads default font on InitWindow()
|
|
593
605
|
extern void UnloadFontDefault(void); // [Module: text] Unloads default font from GPU memory
|
|
594
606
|
#endif
|
|
@@ -601,6 +613,9 @@ static bool InitGraphicsDevice(int width, int height); // Initialize graphics d
|
|
|
601
613
|
static void SetupFramebuffer(int width, int height); // Setup main framebuffer
|
|
602
614
|
static void SetupViewport(int width, int height); // Set viewport for a provided width and height
|
|
603
615
|
|
|
616
|
+
static void ScanDirectoryFiles(const char *basePath, FilePathList *list, const char *filter); // Scan all files and directories in a base path
|
|
617
|
+
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *list, const char *filter); // Scan all files and directories recursively from a base path
|
|
618
|
+
|
|
604
619
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
605
620
|
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
|
606
621
|
// Window callbacks events
|
|
@@ -626,11 +641,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|
|
626
641
|
#endif
|
|
627
642
|
|
|
628
643
|
#if defined(PLATFORM_WEB)
|
|
644
|
+
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData);
|
|
645
|
+
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
|
646
|
+
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
|
|
647
|
+
|
|
629
648
|
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
|
|
630
649
|
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
|
631
650
|
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
|
|
632
|
-
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *e, void *userData);
|
|
633
|
-
|
|
634
651
|
#endif
|
|
635
652
|
|
|
636
653
|
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
|
@@ -668,6 +685,10 @@ static void PlayAutomationEvent(unsigned int frame); // Play frame events
|
|
|
668
685
|
void __stdcall Sleep(unsigned long msTimeout); // Required for: WaitTime()
|
|
669
686
|
#endif
|
|
670
687
|
|
|
688
|
+
#if !defined(SUPPORT_MODULE_RTEXT)
|
|
689
|
+
const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
|
|
690
|
+
#endif // !SUPPORT_MODULE_RTEXT
|
|
691
|
+
|
|
671
692
|
//----------------------------------------------------------------------------------
|
|
672
693
|
// Module Functions Definition - Window and OpenGL Context Functions
|
|
673
694
|
//----------------------------------------------------------------------------------
|
|
@@ -698,13 +719,46 @@ void InitWindow(int width, int height, const char *title)
|
|
|
698
719
|
{
|
|
699
720
|
TRACELOG(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
|
|
700
721
|
|
|
722
|
+
TRACELOG(LOG_INFO, "Supported raylib modules:");
|
|
723
|
+
TRACELOG(LOG_INFO, " > rcore:..... loaded (mandatory)");
|
|
724
|
+
TRACELOG(LOG_INFO, " > rlgl:...... loaded (mandatory)");
|
|
725
|
+
#if defined(SUPPORT_MODULE_RSHAPES)
|
|
726
|
+
TRACELOG(LOG_INFO, " > rshapes:... loaded (optional)");
|
|
727
|
+
#else
|
|
728
|
+
TRACELOG(LOG_INFO, " > rshapes:... not loaded (optional)");
|
|
729
|
+
#endif
|
|
730
|
+
#if defined(SUPPORT_MODULE_RTEXTURES)
|
|
731
|
+
TRACELOG(LOG_INFO, " > rtextures:. loaded (optional)");
|
|
732
|
+
#else
|
|
733
|
+
TRACELOG(LOG_INFO, " > rtextures:. not loaded (optional)");
|
|
734
|
+
#endif
|
|
735
|
+
#if defined(SUPPORT_MODULE_RTEXT)
|
|
736
|
+
TRACELOG(LOG_INFO, " > rtext:..... loaded (optional)");
|
|
737
|
+
#else
|
|
738
|
+
TRACELOG(LOG_INFO, " > rtext:..... not loaded (optional)");
|
|
739
|
+
#endif
|
|
740
|
+
#if defined(SUPPORT_MODULE_RMODELS)
|
|
741
|
+
TRACELOG(LOG_INFO, " > rmodels:... loaded (optional)");
|
|
742
|
+
#else
|
|
743
|
+
TRACELOG(LOG_INFO, " > rmodels:... not loaded (optional)");
|
|
744
|
+
#endif
|
|
745
|
+
#if defined(SUPPORT_MODULE_RAUDIO)
|
|
746
|
+
TRACELOG(LOG_INFO, " > raudio:.... loaded (optional)");
|
|
747
|
+
#else
|
|
748
|
+
TRACELOG(LOG_INFO, " > raudio:.... not loaded (optional)");
|
|
749
|
+
#endif
|
|
750
|
+
|
|
701
751
|
if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title;
|
|
702
752
|
|
|
703
|
-
// Initialize
|
|
753
|
+
// Initialize global input state
|
|
754
|
+
memset(&CORE.Input, 0, sizeof(CORE.Input));
|
|
704
755
|
CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
|
|
705
756
|
CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
|
|
706
757
|
CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW;
|
|
707
758
|
CORE.Input.Gamepad.lastButtonPressed = -1;
|
|
759
|
+
#if defined(SUPPORT_EVENTS_WAITING)
|
|
760
|
+
CORE.Window.eventWaiting = true;
|
|
761
|
+
#endif
|
|
708
762
|
|
|
709
763
|
#if defined(PLATFORM_ANDROID)
|
|
710
764
|
CORE.Window.screen.width = width;
|
|
@@ -791,24 +845,30 @@ void InitWindow(int width, int height, const char *title)
|
|
|
791
845
|
// Initialize base path for storage
|
|
792
846
|
CORE.Storage.basePath = GetWorkingDirectory();
|
|
793
847
|
|
|
794
|
-
#if defined(SUPPORT_DEFAULT_FONT)
|
|
848
|
+
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
795
849
|
// Load default font
|
|
796
|
-
//
|
|
850
|
+
// WARNING: External function: Module required: rtext
|
|
797
851
|
LoadFontDefault();
|
|
852
|
+
#if defined(SUPPORT_MODULE_RSHAPES)
|
|
798
853
|
Rectangle rec = GetFontDefault().recs[95];
|
|
799
854
|
// NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
|
|
800
|
-
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
|
|
855
|
+
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes
|
|
856
|
+
#endif
|
|
801
857
|
#else
|
|
858
|
+
#if defined(SUPPORT_MODULE_RSHAPES)
|
|
802
859
|
// Set default texture and rectangle to be used for shapes drawing
|
|
803
860
|
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
|
804
861
|
Texture2D texture = { rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
|
805
|
-
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f });
|
|
862
|
+
SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes
|
|
863
|
+
#endif
|
|
806
864
|
#endif
|
|
807
|
-
#if defined(
|
|
865
|
+
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
808
866
|
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
|
809
867
|
{
|
|
810
868
|
// Set default font texture filter for HighDPI (blurry)
|
|
811
|
-
|
|
869
|
+
// RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
|
|
870
|
+
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
|
871
|
+
rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
|
|
812
872
|
}
|
|
813
873
|
#endif
|
|
814
874
|
|
|
@@ -820,13 +880,18 @@ void InitWindow(int width, int height, const char *title)
|
|
|
820
880
|
#endif
|
|
821
881
|
|
|
822
882
|
#if defined(PLATFORM_WEB)
|
|
883
|
+
// Setup callback funtions for the DOM events
|
|
884
|
+
emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
|
|
885
|
+
|
|
886
|
+
// WARNING: Below resize code was breaking fullscreen mode for sample games and examples, it needs review
|
|
823
887
|
// Check fullscreen change events(note this is done on the window since most browsers don't support this on #canvas)
|
|
824
888
|
//emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
|
825
889
|
// Check Resize event (note this is done on the window since most browsers don't support this on #canvas)
|
|
826
|
-
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
|
890
|
+
//emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
|
|
827
891
|
// Trigger this once to get initial window sizing
|
|
828
|
-
EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
|
|
829
|
-
|
|
892
|
+
//EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
|
|
893
|
+
|
|
894
|
+
// Support keyboard events -> Not used, GLFW.JS takes care of that
|
|
830
895
|
//emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
|
831
896
|
//emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
|
832
897
|
|
|
@@ -867,8 +932,8 @@ void CloseWindow(void)
|
|
|
867
932
|
}
|
|
868
933
|
#endif
|
|
869
934
|
|
|
870
|
-
#if defined(SUPPORT_DEFAULT_FONT)
|
|
871
|
-
UnloadFontDefault();
|
|
935
|
+
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
936
|
+
UnloadFontDefault(); // WARNING: Module required: rtext
|
|
872
937
|
#endif
|
|
873
938
|
|
|
874
939
|
rlglClose(); // De-init rlgl
|
|
@@ -1109,39 +1174,38 @@ bool IsWindowState(unsigned int flag)
|
|
|
1109
1174
|
void ToggleFullscreen(void)
|
|
1110
1175
|
{
|
|
1111
1176
|
#if defined(PLATFORM_DESKTOP)
|
|
1112
|
-
// NOTE: glfwSetWindowMonitor() doesn't work properly (bugs)
|
|
1113
1177
|
if (!CORE.Window.fullscreen)
|
|
1114
1178
|
{
|
|
1115
1179
|
// Store previous window position (in case we exit fullscreen)
|
|
1116
1180
|
glfwGetWindowPos(CORE.Window.handle, &CORE.Window.position.x, &CORE.Window.position.y);
|
|
1117
1181
|
|
|
1118
1182
|
int monitorCount = 0;
|
|
1119
|
-
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
|
|
1120
|
-
|
|
1121
1183
|
int monitorIndex = GetCurrentMonitor();
|
|
1184
|
+
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
|
|
1122
1185
|
|
|
1123
1186
|
// Use current monitor, so we correctly get the display the window is on
|
|
1124
|
-
GLFWmonitor*
|
|
1187
|
+
GLFWmonitor *monitor = (monitorIndex < monitorCount)? monitors[monitorIndex] : NULL;
|
|
1125
1188
|
|
|
1126
|
-
if (
|
|
1189
|
+
if (monitor == NULL)
|
|
1127
1190
|
{
|
|
1128
1191
|
TRACELOG(LOG_WARNING, "GLFW: Failed to get monitor");
|
|
1129
1192
|
|
|
1130
|
-
CORE.Window.fullscreen = false;
|
|
1193
|
+
CORE.Window.fullscreen = false;
|
|
1131
1194
|
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
|
1132
1195
|
|
|
1133
1196
|
glfwSetWindowMonitor(CORE.Window.handle, NULL, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
|
1134
|
-
return;
|
|
1135
1197
|
}
|
|
1198
|
+
else
|
|
1199
|
+
{
|
|
1200
|
+
CORE.Window.fullscreen = true;
|
|
1201
|
+
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
|
1136
1202
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
glfwSetWindowMonitor(CORE.Window.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
|
1203
|
+
glfwSetWindowMonitor(CORE.Window.handle, monitor, 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
|
1204
|
+
}
|
|
1141
1205
|
}
|
|
1142
1206
|
else
|
|
1143
1207
|
{
|
|
1144
|
-
CORE.Window.fullscreen = false;
|
|
1208
|
+
CORE.Window.fullscreen = false;
|
|
1145
1209
|
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
|
1146
1210
|
|
|
1147
1211
|
glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
|
|
@@ -1152,6 +1216,7 @@ void ToggleFullscreen(void)
|
|
|
1152
1216
|
if (CORE.Window.flags & FLAG_VSYNC_HINT) glfwSwapInterval(1);
|
|
1153
1217
|
#endif
|
|
1154
1218
|
#if defined(PLATFORM_WEB)
|
|
1219
|
+
/*
|
|
1155
1220
|
EM_ASM
|
|
1156
1221
|
(
|
|
1157
1222
|
// This strategy works well while using raylib minimal web shell for emscripten,
|
|
@@ -1159,14 +1224,17 @@ void ToggleFullscreen(void)
|
|
|
1159
1224
|
// is a good strategy but maybe games prefer to keep current canvas resolution and
|
|
1160
1225
|
// display it in fullscreen, adjusting monitor resolution if possible
|
|
1161
1226
|
if (document.fullscreenElement) document.exitFullscreen();
|
|
1162
|
-
else Module.requestFullscreen(false, true);
|
|
1227
|
+
else Module.requestFullscreen(true, true); //false, true);
|
|
1163
1228
|
);
|
|
1164
|
-
|
|
1229
|
+
*/
|
|
1230
|
+
//EM_ASM(Module.requestFullscreen(false, false););
|
|
1165
1231
|
/*
|
|
1166
1232
|
if (!CORE.Window.fullscreen)
|
|
1167
1233
|
{
|
|
1168
1234
|
// Option 1: Request fullscreen for the canvas element
|
|
1169
|
-
// This option does not seem to work at all
|
|
1235
|
+
// This option does not seem to work at all:
|
|
1236
|
+
// emscripten_request_pointerlock() and emscripten_request_fullscreen() are affected by web security,
|
|
1237
|
+
// the user must click once on the canvas to hide the pointer or transition to full screen
|
|
1170
1238
|
//emscripten_request_fullscreen("#canvas", false);
|
|
1171
1239
|
|
|
1172
1240
|
// Option 2: Request fullscreen for the canvas element with strategy
|
|
@@ -1195,20 +1263,25 @@ void ToggleFullscreen(void)
|
|
|
1195
1263
|
int width, height;
|
|
1196
1264
|
emscripten_get_canvas_element_size("#canvas", &width, &height);
|
|
1197
1265
|
TRACELOG(LOG_WARNING, "Emscripten: Enter fullscreen: Canvas size: %i x %i", width, height);
|
|
1266
|
+
|
|
1267
|
+
CORE.Window.fullscreen = true; // Toggle fullscreen flag
|
|
1268
|
+
CORE.Window.flags |= FLAG_FULLSCREEN_MODE;
|
|
1198
1269
|
}
|
|
1199
1270
|
else
|
|
1200
1271
|
{
|
|
1201
1272
|
//emscripten_exit_fullscreen();
|
|
1202
|
-
emscripten_exit_soft_fullscreen();
|
|
1273
|
+
//emscripten_exit_soft_fullscreen();
|
|
1203
1274
|
|
|
1204
1275
|
int width, height;
|
|
1205
1276
|
emscripten_get_canvas_element_size("#canvas", &width, &height);
|
|
1206
1277
|
TRACELOG(LOG_WARNING, "Emscripten: Exit fullscreen: Canvas size: %i x %i", width, height);
|
|
1278
|
+
|
|
1279
|
+
CORE.Window.fullscreen = false; // Toggle fullscreen flag
|
|
1280
|
+
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
|
1207
1281
|
}
|
|
1208
1282
|
*/
|
|
1209
1283
|
|
|
1210
1284
|
CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
|
|
1211
|
-
CORE.Window.flags ^= FLAG_FULLSCREEN_MODE;
|
|
1212
1285
|
#endif
|
|
1213
1286
|
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
|
|
1214
1287
|
TRACELOG(LOG_WARNING, "SYSTEM: Failed to toggle to windowed mode");
|
|
@@ -1339,6 +1412,13 @@ void SetWindowState(unsigned int flags)
|
|
|
1339
1412
|
TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
|
|
1340
1413
|
}
|
|
1341
1414
|
|
|
1415
|
+
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
|
1416
|
+
if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) != (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
|
|
1417
|
+
{
|
|
1418
|
+
glfwSetWindowAttrib(CORE.Window.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
|
|
1419
|
+
CORE.Window.flags |= FLAG_WINDOW_MOUSE_PASSTHROUGH;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1342
1422
|
// State change: FLAG_MSAA_4X_HINT
|
|
1343
1423
|
if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) != (flags & FLAG_MSAA_4X_HINT)) && ((flags & FLAG_MSAA_4X_HINT) > 0))
|
|
1344
1424
|
{
|
|
@@ -1440,6 +1520,13 @@ void ClearWindowState(unsigned int flags)
|
|
|
1440
1520
|
TRACELOG(LOG_WARNING, "WINDOW: High DPI can only by configured before window initialization");
|
|
1441
1521
|
}
|
|
1442
1522
|
|
|
1523
|
+
// State change: FLAG_WINDOW_MOUSE_PASSTHROUGH
|
|
1524
|
+
if (((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) && ((flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0))
|
|
1525
|
+
{
|
|
1526
|
+
glfwSetWindowAttrib(CORE.Window.handle, GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);
|
|
1527
|
+
CORE.Window.flags &= ~FLAG_WINDOW_MOUSE_PASSTHROUGH;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1443
1530
|
// State change: FLAG_MSAA_4X_HINT
|
|
1444
1531
|
if (((CORE.Window.flags & FLAG_MSAA_4X_HINT) > 0) && ((flags & FLAG_MSAA_4X_HINT) > 0))
|
|
1445
1532
|
{
|
|
@@ -1525,12 +1612,15 @@ void SetWindowSize(int width, int height)
|
|
|
1525
1612
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
1526
1613
|
glfwSetWindowSize(CORE.Window.handle, width, height);
|
|
1527
1614
|
#endif
|
|
1528
|
-
|
|
1529
|
-
//emscripten_set_canvas_size(width, height); // DEPRECATED!
|
|
1615
|
+
}
|
|
1530
1616
|
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1617
|
+
// Set window opacity, value opacity is between 0.0 and 1.0
|
|
1618
|
+
void SetWindowOpacity(float opacity)
|
|
1619
|
+
{
|
|
1620
|
+
#if defined(PLATFORM_DESKTOP)
|
|
1621
|
+
if (opacity >= 1.0f) opacity = 1.0f;
|
|
1622
|
+
else if (opacity <= 0.0f) opacity = 0.0f;
|
|
1623
|
+
glfwSetWindowOpacity(CORE.Window.handle, opacity);
|
|
1534
1624
|
#endif
|
|
1535
1625
|
}
|
|
1536
1626
|
|
|
@@ -1640,7 +1730,7 @@ int GetCurrentMonitor(void)
|
|
|
1640
1730
|
#endif
|
|
1641
1731
|
}
|
|
1642
1732
|
|
|
1643
|
-
// Get selected monitor
|
|
1733
|
+
// Get selected monitor position
|
|
1644
1734
|
Vector2 GetMonitorPosition(int monitor)
|
|
1645
1735
|
{
|
|
1646
1736
|
#if defined(PLATFORM_DESKTOP)
|
|
@@ -1659,7 +1749,7 @@ Vector2 GetMonitorPosition(int monitor)
|
|
|
1659
1749
|
return (Vector2){ 0, 0 };
|
|
1660
1750
|
}
|
|
1661
1751
|
|
|
1662
|
-
// Get selected monitor width (
|
|
1752
|
+
// Get selected monitor width (currently used by monitor)
|
|
1663
1753
|
int GetMonitorWidth(int monitor)
|
|
1664
1754
|
{
|
|
1665
1755
|
#if defined(PLATFORM_DESKTOP)
|
|
@@ -1668,11 +1758,9 @@ int GetMonitorWidth(int monitor)
|
|
|
1668
1758
|
|
|
1669
1759
|
if ((monitor >= 0) && (monitor < monitorCount))
|
|
1670
1760
|
{
|
|
1671
|
-
|
|
1672
|
-
const GLFWvidmode *modes = glfwGetVideoModes(monitors[monitor], &count);
|
|
1761
|
+
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
|
|
1673
1762
|
|
|
1674
|
-
|
|
1675
|
-
if (count > 0) return modes[count - 1].width;
|
|
1763
|
+
if (mode) return mode->width;
|
|
1676
1764
|
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
|
|
1677
1765
|
}
|
|
1678
1766
|
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
|
|
@@ -1680,7 +1768,7 @@ int GetMonitorWidth(int monitor)
|
|
|
1680
1768
|
return 0;
|
|
1681
1769
|
}
|
|
1682
1770
|
|
|
1683
|
-
// Get selected monitor
|
|
1771
|
+
// Get selected monitor height (currently used by monitor)
|
|
1684
1772
|
int GetMonitorHeight(int monitor)
|
|
1685
1773
|
{
|
|
1686
1774
|
#if defined(PLATFORM_DESKTOP)
|
|
@@ -1689,11 +1777,9 @@ int GetMonitorHeight(int monitor)
|
|
|
1689
1777
|
|
|
1690
1778
|
if ((monitor >= 0) && (monitor < monitorCount))
|
|
1691
1779
|
{
|
|
1692
|
-
|
|
1693
|
-
const GLFWvidmode *modes = glfwGetVideoModes(monitors[monitor], &count);
|
|
1780
|
+
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
|
|
1694
1781
|
|
|
1695
|
-
|
|
1696
|
-
if (count > 0) return modes[count - 1].height;
|
|
1782
|
+
if (mode) return mode->height;
|
|
1697
1783
|
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
|
|
1698
1784
|
}
|
|
1699
1785
|
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
|
|
@@ -1820,25 +1906,44 @@ const char *GetMonitorName(int monitor)
|
|
|
1820
1906
|
return "";
|
|
1821
1907
|
}
|
|
1822
1908
|
|
|
1823
|
-
//
|
|
1824
|
-
|
|
1825
|
-
const char *GetClipboardText(void)
|
|
1909
|
+
// Set clipboard text content
|
|
1910
|
+
void SetClipboardText(const char *text)
|
|
1826
1911
|
{
|
|
1827
1912
|
#if defined(PLATFORM_DESKTOP)
|
|
1828
|
-
|
|
1829
|
-
#
|
|
1830
|
-
|
|
1913
|
+
glfwSetClipboardString(CORE.Window.handle, text);
|
|
1914
|
+
#endif
|
|
1915
|
+
#if defined(PLATFORM_WEB)
|
|
1916
|
+
emscripten_run_script(TextFormat("navigator.clipboard.writeText('%s')", text));
|
|
1831
1917
|
#endif
|
|
1832
1918
|
}
|
|
1833
1919
|
|
|
1834
|
-
//
|
|
1835
|
-
void
|
|
1920
|
+
// Enable waiting for events on EndDrawing(), no automatic event polling
|
|
1921
|
+
void EnableEventWaiting(void)
|
|
1922
|
+
{
|
|
1923
|
+
CORE.Window.eventWaiting = true;
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
// Disable waiting for events on EndDrawing(), automatic events polling
|
|
1927
|
+
RLAPI void DisableEventWaiting(void)
|
|
1928
|
+
{
|
|
1929
|
+
CORE.Window.eventWaiting = false;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
// Get clipboard text content
|
|
1933
|
+
// NOTE: returned string is allocated and freed by GLFW
|
|
1934
|
+
const char *GetClipboardText(void)
|
|
1836
1935
|
{
|
|
1837
1936
|
#if defined(PLATFORM_DESKTOP)
|
|
1838
|
-
|
|
1937
|
+
return glfwGetClipboardString(CORE.Window.handle);
|
|
1938
|
+
#endif
|
|
1939
|
+
#if defined(PLATFORM_WEB)
|
|
1940
|
+
return emscripten_run_script_string("navigator.clipboard.readText()");
|
|
1839
1941
|
#endif
|
|
1942
|
+
return NULL;
|
|
1840
1943
|
}
|
|
1841
1944
|
|
|
1945
|
+
|
|
1946
|
+
|
|
1842
1947
|
// Show mouse cursor
|
|
1843
1948
|
void ShowCursor(void)
|
|
1844
1949
|
{
|
|
@@ -1926,15 +2031,6 @@ void EndDrawing(void)
|
|
|
1926
2031
|
{
|
|
1927
2032
|
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
|
1928
2033
|
|
|
1929
|
-
#if defined(SUPPORT_MOUSE_CURSOR_POINT)
|
|
1930
|
-
// Draw a small rectangle on mouse position for user reference
|
|
1931
|
-
if (!CORE.Input.Mouse.cursorHidden)
|
|
1932
|
-
{
|
|
1933
|
-
DrawRectangle(CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y, 3, 3, MAROON);
|
|
1934
|
-
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
|
1935
|
-
}
|
|
1936
|
-
#endif
|
|
1937
|
-
|
|
1938
2034
|
#if defined(SUPPORT_GIF_RECORDING)
|
|
1939
2035
|
// Draw record indicator
|
|
1940
2036
|
if (gifRecording)
|
|
@@ -1947,17 +2043,20 @@ void EndDrawing(void)
|
|
|
1947
2043
|
{
|
|
1948
2044
|
// Get image data for the current frame (from backbuffer)
|
|
1949
2045
|
// NOTE: This process is quite slow... :(
|
|
1950
|
-
|
|
1951
|
-
|
|
2046
|
+
Vector2 scale = GetWindowScaleDPI();
|
|
2047
|
+
unsigned char *screenData = rlReadScreenPixels((int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y));
|
|
2048
|
+
msf_gif_frame(&gifState, screenData, 10, 16, (int)((float)CORE.Window.render.width*scale.x)*4);
|
|
1952
2049
|
|
|
1953
2050
|
RL_FREE(screenData); // Free image data
|
|
1954
2051
|
}
|
|
1955
2052
|
|
|
2053
|
+
#if defined(SUPPORT_MODULE_RSHAPES) && defined(SUPPORT_MODULE_RTEXT)
|
|
1956
2054
|
if (((gifFrameCounter/15)%2) == 1)
|
|
1957
2055
|
{
|
|
1958
|
-
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON);
|
|
1959
|
-
DrawText("GIF RECORDING", 50, CORE.Window.screen.height - 25, 10, RED);
|
|
2056
|
+
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON); // WARNING: Module required: rshapes
|
|
2057
|
+
DrawText("GIF RECORDING", 50, CORE.Window.screen.height - 25, 10, RED); // WARNING: Module required: rtext
|
|
1960
2058
|
}
|
|
2059
|
+
#endif
|
|
1961
2060
|
|
|
1962
2061
|
rlDrawRenderBatchActive(); // Update and draw internal render batch
|
|
1963
2062
|
}
|
|
@@ -2004,7 +2103,7 @@ void EndDrawing(void)
|
|
|
2004
2103
|
// Wait for some milliseconds...
|
|
2005
2104
|
if (CORE.Time.frame < CORE.Time.target)
|
|
2006
2105
|
{
|
|
2007
|
-
WaitTime(
|
|
2106
|
+
WaitTime(CORE.Time.target - CORE.Time.frame);
|
|
2008
2107
|
|
|
2009
2108
|
CORE.Time.current = GetTime();
|
|
2010
2109
|
double waitTime = CORE.Time.current - CORE.Time.previous;
|
|
@@ -2115,8 +2214,10 @@ void BeginTextureMode(RenderTexture2D target)
|
|
|
2115
2214
|
|
|
2116
2215
|
rlEnableFramebuffer(target.id); // Enable render target
|
|
2117
2216
|
|
|
2118
|
-
// Set viewport
|
|
2217
|
+
// Set viewport and RLGL internal framebuffer size
|
|
2119
2218
|
rlViewport(0, 0, target.texture.width, target.texture.height);
|
|
2219
|
+
rlSetFramebufferWidth(target.texture.width);
|
|
2220
|
+
rlSetFramebufferHeight(target.texture.height);
|
|
2120
2221
|
|
|
2121
2222
|
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
|
|
2122
2223
|
rlLoadIdentity(); // Reset current matrix (projection)
|
|
@@ -2184,16 +2285,20 @@ void BeginScissorMode(int x, int y, int width, int height)
|
|
|
2184
2285
|
|
|
2185
2286
|
rlEnableScissorTest();
|
|
2186
2287
|
|
|
2288
|
+
#if defined(__APPLE__)
|
|
2289
|
+
Vector2 scale = GetWindowScaleDPI();
|
|
2290
|
+
rlScissor((int)(x*scale.x), (int)(GetScreenHeight()*scale.y - (((y + height)*scale.y))), (int)(width*scale.x), (int)(height*scale.y));
|
|
2291
|
+
#else
|
|
2187
2292
|
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
|
2188
2293
|
{
|
|
2189
2294
|
Vector2 scale = GetWindowScaleDPI();
|
|
2190
|
-
|
|
2191
2295
|
rlScissor((int)(x*scale.x), (int)(CORE.Window.currentFbo.height - (y + height)*scale.y), (int)(width*scale.x), (int)(height*scale.y));
|
|
2192
2296
|
}
|
|
2193
2297
|
else
|
|
2194
2298
|
{
|
|
2195
2299
|
rlScissor(x, CORE.Window.currentFbo.height - (y + height), width, height);
|
|
2196
2300
|
}
|
|
2301
|
+
#endif
|
|
2197
2302
|
}
|
|
2198
2303
|
|
|
2199
2304
|
// End scissor mode
|
|
@@ -2258,8 +2363,8 @@ VrStereoConfig LoadVrStereoConfig(VrDeviceInfo device)
|
|
|
2258
2363
|
|
|
2259
2364
|
// Fovy is normally computed with: 2*atan2f(device.vScreenSize, 2*device.eyeToScreenDistance)
|
|
2260
2365
|
// ...but with lens distortion it is increased (see Oculus SDK Documentation)
|
|
2261
|
-
|
|
2262
|
-
|
|
2366
|
+
float fovy = 2.0f*atan2f(device.vScreenSize*0.5f*distortionScale, device.eyeToScreenDistance); // Really need distortionScale?
|
|
2367
|
+
// float fovy = 2.0f*(float)atan2f(device.vScreenSize*0.5f, device.eyeToScreenDistance);
|
|
2263
2368
|
|
|
2264
2369
|
// Compute camera projection matrices
|
|
2265
2370
|
float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1]
|
|
@@ -2585,7 +2690,7 @@ void SetTargetFPS(int fps)
|
|
|
2585
2690
|
if (fps < 1) CORE.Time.target = 0.0;
|
|
2586
2691
|
else CORE.Time.target = 1.0/(double)fps;
|
|
2587
2692
|
|
|
2588
|
-
TRACELOG(LOG_INFO, "TIMER: Target time per frame: %02.03f milliseconds", (float)CORE.Time.target*1000);
|
|
2693
|
+
TRACELOG(LOG_INFO, "TIMER: Target time per frame: %02.03f milliseconds", (float)CORE.Time.target*1000.0f);
|
|
2589
2694
|
}
|
|
2590
2695
|
|
|
2591
2696
|
// Get current FPS
|
|
@@ -2661,13 +2766,15 @@ void SetConfigFlags(unsigned int flags)
|
|
|
2661
2766
|
// Takes a screenshot of current screen (saved a .png)
|
|
2662
2767
|
void TakeScreenshot(const char *fileName)
|
|
2663
2768
|
{
|
|
2664
|
-
|
|
2665
|
-
|
|
2769
|
+
#if defined(SUPPORT_MODULE_RTEXTURES)
|
|
2770
|
+
Vector2 scale = GetWindowScaleDPI();
|
|
2771
|
+
unsigned char *imgData = rlReadScreenPixels((int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y));
|
|
2772
|
+
Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
|
2666
2773
|
|
|
2667
|
-
char path[
|
|
2774
|
+
char path[2048] = { 0 };
|
|
2668
2775
|
strcpy(path, TextFormat("%s/%s", CORE.Storage.basePath, fileName));
|
|
2669
2776
|
|
|
2670
|
-
ExportImage(image, path);
|
|
2777
|
+
ExportImage(image, path); // WARNING: Module required: rtextures
|
|
2671
2778
|
RL_FREE(imgData);
|
|
2672
2779
|
|
|
2673
2780
|
#if defined(PLATFORM_WEB)
|
|
@@ -2677,6 +2784,9 @@ void TakeScreenshot(const char *fileName)
|
|
|
2677
2784
|
#endif
|
|
2678
2785
|
|
|
2679
2786
|
TRACELOG(LOG_INFO, "SYSTEM: [%s] Screenshot taken successfully", path);
|
|
2787
|
+
#else
|
|
2788
|
+
TRACELOG(LOG_WARNING,"IMAGE: ExportImage() requires module: rtextures");
|
|
2789
|
+
#endif
|
|
2680
2790
|
}
|
|
2681
2791
|
|
|
2682
2792
|
// Get a random value between min and max (both included)
|
|
@@ -2709,6 +2819,11 @@ bool FileExists(const char *fileName)
|
|
|
2709
2819
|
if (access(fileName, F_OK) != -1) result = true;
|
|
2710
2820
|
#endif
|
|
2711
2821
|
|
|
2822
|
+
// NOTE: Alternatively, stat() can be used instead of access()
|
|
2823
|
+
//#include <sys/stat.h>
|
|
2824
|
+
//struct stat statbuf;
|
|
2825
|
+
//if (stat(filename, &statbuf) == 0) result = true;
|
|
2826
|
+
|
|
2712
2827
|
return result;
|
|
2713
2828
|
}
|
|
2714
2829
|
|
|
@@ -2716,21 +2831,23 @@ bool FileExists(const char *fileName)
|
|
|
2716
2831
|
// NOTE: Extensions checking is not case-sensitive
|
|
2717
2832
|
bool IsFileExtension(const char *fileName, const char *ext)
|
|
2718
2833
|
{
|
|
2834
|
+
#define MAX_FILE_EXTENSION_SIZE 16
|
|
2835
|
+
|
|
2719
2836
|
bool result = false;
|
|
2720
2837
|
const char *fileExt = GetFileExtension(fileName);
|
|
2721
2838
|
|
|
2722
2839
|
if (fileExt != NULL)
|
|
2723
2840
|
{
|
|
2724
|
-
#if defined(SUPPORT_TEXT_MANIPULATION)
|
|
2841
|
+
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_TEXT_MANIPULATION)
|
|
2725
2842
|
int extCount = 0;
|
|
2726
|
-
const char **checkExts = TextSplit(ext, ';', &extCount);
|
|
2843
|
+
const char **checkExts = TextSplit(ext, ';', &extCount); // WARNING: Module required: rtext
|
|
2727
2844
|
|
|
2728
|
-
char fileExtLower[
|
|
2729
|
-
|
|
2845
|
+
char fileExtLower[MAX_FILE_EXTENSION_SIZE] = { 0 };
|
|
2846
|
+
strncpy(fileExtLower, TextToLower(fileExt),MAX_FILE_EXTENSION_SIZE); // WARNING: Module required: rtext
|
|
2730
2847
|
|
|
2731
2848
|
for (int i = 0; i < extCount; i++)
|
|
2732
2849
|
{
|
|
2733
|
-
if (
|
|
2850
|
+
if (strcmp(fileExtLower, TextToLower(checkExts[i])) == 0)
|
|
2734
2851
|
{
|
|
2735
2852
|
result = true;
|
|
2736
2853
|
break;
|
|
@@ -2759,6 +2876,24 @@ bool DirectoryExists(const char *dirPath)
|
|
|
2759
2876
|
return result;
|
|
2760
2877
|
}
|
|
2761
2878
|
|
|
2879
|
+
// Get file length in bytes
|
|
2880
|
+
// NOTE: GetFileSize() conflicts with windows.h
|
|
2881
|
+
int GetFileLength(const char *fileName)
|
|
2882
|
+
{
|
|
2883
|
+
int size = 0;
|
|
2884
|
+
|
|
2885
|
+
FILE *file = fopen(fileName, "rb");
|
|
2886
|
+
|
|
2887
|
+
if (file != NULL)
|
|
2888
|
+
{
|
|
2889
|
+
fseek(file, 0L, SEEK_END);
|
|
2890
|
+
size = (int)ftell(file);
|
|
2891
|
+
fclose(file);
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
return size;
|
|
2895
|
+
}
|
|
2896
|
+
|
|
2762
2897
|
// Get pointer to extension for a filename string (includes the dot: .png)
|
|
2763
2898
|
const char *GetFileExtension(const char *fileName)
|
|
2764
2899
|
{
|
|
@@ -2791,7 +2926,7 @@ const char *GetFileName(const char *filePath)
|
|
|
2791
2926
|
// Get filename string without extension (uses static string)
|
|
2792
2927
|
const char *GetFileNameWithoutExt(const char *filePath)
|
|
2793
2928
|
{
|
|
2794
|
-
#define MAX_FILENAMEWITHOUTEXT_LENGTH
|
|
2929
|
+
#define MAX_FILENAMEWITHOUTEXT_LENGTH 256
|
|
2795
2930
|
|
|
2796
2931
|
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 };
|
|
2797
2932
|
memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH);
|
|
@@ -2894,55 +3029,148 @@ const char *GetWorkingDirectory(void)
|
|
|
2894
3029
|
return path;
|
|
2895
3030
|
}
|
|
2896
3031
|
|
|
2897
|
-
|
|
2898
|
-
// NOTE: Files count is returned by parameters pointer
|
|
2899
|
-
char **GetDirectoryFiles(const char *dirPath, int *fileCount)
|
|
3032
|
+
const char *GetApplicationDirectory(void)
|
|
2900
3033
|
{
|
|
2901
|
-
|
|
3034
|
+
static char appDir[MAX_FILEPATH_LENGTH] = { 0 };
|
|
3035
|
+
memset(appDir, 0, MAX_FILEPATH_LENGTH);
|
|
3036
|
+
|
|
3037
|
+
#if defined(_WIN32)
|
|
3038
|
+
int len = 0;
|
|
3039
|
+
#if defined (UNICODE)
|
|
3040
|
+
unsigned short widePath[MAX_PATH];
|
|
3041
|
+
len = GetModuleFileNameW(NULL, widePath, MAX_PATH);
|
|
3042
|
+
len = WideCharToMultiByte(0, 0, widePath, len, appDir, MAX_PATH, NULL, NULL);
|
|
3043
|
+
#else
|
|
3044
|
+
len = GetModuleFileNameA(NULL, appDir, MAX_PATH);
|
|
3045
|
+
#endif
|
|
3046
|
+
if (len > 0)
|
|
3047
|
+
{
|
|
3048
|
+
for (int i = len; i >= 0; --i)
|
|
3049
|
+
{
|
|
3050
|
+
if (appDir[i] == '\\')
|
|
3051
|
+
{
|
|
3052
|
+
appDir[i + 1] = '\0';
|
|
3053
|
+
break;
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
else
|
|
3058
|
+
{
|
|
3059
|
+
appDir[0] = '.';
|
|
3060
|
+
appDir[1] = '\\';
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
#elif defined(__linux__)
|
|
3064
|
+
unsigned int size = sizeof(appDir);
|
|
3065
|
+
ssize_t len = readlink("/proc/self/exe", appDir, size);
|
|
3066
|
+
|
|
3067
|
+
if (len > 0)
|
|
3068
|
+
{
|
|
3069
|
+
for (int i = len; i >= 0; --i)
|
|
3070
|
+
{
|
|
3071
|
+
if (appDir[i] == '/')
|
|
3072
|
+
{
|
|
3073
|
+
appDir[i + 1] = '\0';
|
|
3074
|
+
break;
|
|
3075
|
+
}
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
else
|
|
3079
|
+
{
|
|
3080
|
+
appDir[0] = '.';
|
|
3081
|
+
appDir[1] = '/';
|
|
3082
|
+
}
|
|
3083
|
+
#elif defined(__APPLE__)
|
|
3084
|
+
uint32_t size = sizeof(appDir);
|
|
3085
|
+
|
|
3086
|
+
if (_NSGetExecutablePath(appDir, &size) == 0)
|
|
3087
|
+
{
|
|
3088
|
+
int len = strlen(appDir);
|
|
3089
|
+
for (int i = len; i >= 0; --i)
|
|
3090
|
+
{
|
|
3091
|
+
if (appDir[i] == '/')
|
|
3092
|
+
{
|
|
3093
|
+
appDir[i + 1] = '\0';
|
|
3094
|
+
break;
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
else
|
|
3099
|
+
{
|
|
3100
|
+
appDir[0] = '.';
|
|
3101
|
+
appDir[1] = '/';
|
|
3102
|
+
}
|
|
3103
|
+
#endif
|
|
2902
3104
|
|
|
2903
|
-
|
|
3105
|
+
return appDir;
|
|
3106
|
+
}
|
|
2904
3107
|
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
3108
|
+
// Load directory filepaths
|
|
3109
|
+
// NOTE: Base path is prepended to the scanned filepaths
|
|
3110
|
+
// WARNING: Directory is scanned twice, first time to get files count
|
|
3111
|
+
// No recursive scanning is done!
|
|
3112
|
+
FilePathList LoadDirectoryFiles(const char *dirPath)
|
|
3113
|
+
{
|
|
3114
|
+
FilePathList files = { 0 };
|
|
3115
|
+
unsigned int fileCounter = 0;
|
|
2908
3116
|
|
|
2909
|
-
int counter = 0;
|
|
2910
3117
|
struct dirent *entity;
|
|
2911
3118
|
DIR *dir = opendir(dirPath);
|
|
2912
3119
|
|
|
2913
|
-
if (dir != NULL)
|
|
3120
|
+
if (dir != NULL) // It's a directory
|
|
2914
3121
|
{
|
|
2915
|
-
//
|
|
2916
|
-
// first one to count files and second one to read names
|
|
2917
|
-
// That way we can allocate required memory, instead of a limited pool
|
|
2918
|
-
|
|
3122
|
+
// SCAN 1: Count files
|
|
2919
3123
|
while ((entity = readdir(dir)) != NULL)
|
|
2920
3124
|
{
|
|
2921
|
-
|
|
2922
|
-
|
|
3125
|
+
// NOTE: We skip '.' (current dir) and '..' (parent dir) filepaths
|
|
3126
|
+
if ((strcmp(entity->d_name, ".") != 0) && (strcmp(entity->d_name, "..") != 0)) fileCounter++;
|
|
2923
3127
|
}
|
|
2924
3128
|
|
|
3129
|
+
// Memory allocation for dirFileCount
|
|
3130
|
+
files.capacity = fileCounter;
|
|
3131
|
+
files.paths = (char **)RL_MALLOC(files.capacity*sizeof(char *));
|
|
3132
|
+
for (unsigned int i = 0; i < files.capacity; i++) files.paths[i] = (char *)RL_MALLOC(MAX_FILEPATH_LENGTH*sizeof(char));
|
|
3133
|
+
|
|
2925
3134
|
closedir(dir);
|
|
3135
|
+
|
|
3136
|
+
// SCAN 2: Read filepaths
|
|
3137
|
+
// NOTE: Directory paths are also registered
|
|
3138
|
+
ScanDirectoryFiles(dirPath, &files, NULL);
|
|
3139
|
+
|
|
3140
|
+
// Security check: read files.count should match fileCounter
|
|
3141
|
+
if (files.count != files.capacity) TRACELOG(LOG_WARNING, "FILEIO: Read files count do not match capacity allocated");
|
|
2926
3142
|
}
|
|
2927
3143
|
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file...
|
|
2928
3144
|
|
|
2929
|
-
|
|
2930
|
-
|
|
3145
|
+
return files;
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
// Load directory filepaths with extension filtering and recursive directory scan
|
|
3149
|
+
// NOTE: On recursive loading we do not pre-scan for file count, we use MAX_FILEPATH_CAPACITY
|
|
3150
|
+
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
|
3151
|
+
{
|
|
3152
|
+
FilePathList files = { 0 };
|
|
3153
|
+
|
|
3154
|
+
files.capacity = MAX_FILEPATH_CAPACITY;
|
|
3155
|
+
files.paths = (char **)RL_CALLOC(files.capacity, sizeof(char *));
|
|
3156
|
+
for (unsigned int i = 0; i < files.capacity; i++) files.paths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
|
2931
3157
|
|
|
2932
|
-
|
|
3158
|
+
// WARNING: basePath is always prepended to scanned paths
|
|
3159
|
+
if (scanSubdirs) ScanDirectoryFilesRecursively(basePath, &files, filter);
|
|
3160
|
+
else ScanDirectoryFiles(basePath, &files, filter);
|
|
3161
|
+
|
|
3162
|
+
return files;
|
|
2933
3163
|
}
|
|
2934
3164
|
|
|
2935
|
-
//
|
|
2936
|
-
void
|
|
3165
|
+
// Unload directory filepaths
|
|
3166
|
+
void UnloadDirectoryFiles(FilePathList files)
|
|
2937
3167
|
{
|
|
2938
|
-
if (
|
|
3168
|
+
if (files.capacity > 0)
|
|
2939
3169
|
{
|
|
2940
|
-
for (int i = 0; i <
|
|
3170
|
+
for (unsigned int i = 0; i < files.capacity; i++) RL_FREE(files.paths[i]);
|
|
2941
3171
|
|
|
2942
|
-
RL_FREE(
|
|
3172
|
+
RL_FREE(files.paths);
|
|
2943
3173
|
}
|
|
2944
|
-
|
|
2945
|
-
dirFileCount = 0;
|
|
2946
3174
|
}
|
|
2947
3175
|
|
|
2948
3176
|
// Change working directory, returns true on success
|
|
@@ -2955,6 +3183,15 @@ bool ChangeDirectory(const char *dir)
|
|
|
2955
3183
|
return (result == 0);
|
|
2956
3184
|
}
|
|
2957
3185
|
|
|
3186
|
+
// Check if a given path point to a file
|
|
3187
|
+
bool IsPathFile(const char *path)
|
|
3188
|
+
{
|
|
3189
|
+
struct stat pathStat = { 0 };
|
|
3190
|
+
stat(path, &pathStat);
|
|
3191
|
+
|
|
3192
|
+
return S_ISREG(pathStat.st_mode);
|
|
3193
|
+
}
|
|
3194
|
+
|
|
2958
3195
|
// Check if a file has been dropped into window
|
|
2959
3196
|
bool IsFileDropped(void)
|
|
2960
3197
|
{
|
|
@@ -2962,23 +3199,30 @@ bool IsFileDropped(void)
|
|
|
2962
3199
|
else return false;
|
|
2963
3200
|
}
|
|
2964
3201
|
|
|
2965
|
-
//
|
|
2966
|
-
|
|
3202
|
+
// Load dropped filepaths
|
|
3203
|
+
FilePathList LoadDroppedFiles(void)
|
|
2967
3204
|
{
|
|
2968
|
-
|
|
2969
|
-
|
|
3205
|
+
FilePathList files = { 0 };
|
|
3206
|
+
|
|
3207
|
+
files.count = CORE.Window.dropFileCount;
|
|
3208
|
+
files.paths = CORE.Window.dropFilepaths;
|
|
3209
|
+
|
|
3210
|
+
return files;
|
|
2970
3211
|
}
|
|
2971
3212
|
|
|
2972
|
-
//
|
|
2973
|
-
void
|
|
3213
|
+
// Unload dropped filepaths
|
|
3214
|
+
void UnloadDroppedFiles(FilePathList files)
|
|
2974
3215
|
{
|
|
2975
|
-
|
|
3216
|
+
// WARNING: files pointers are the same as internal ones
|
|
3217
|
+
|
|
3218
|
+
if (files.count > 0)
|
|
2976
3219
|
{
|
|
2977
|
-
for (int i = 0; i <
|
|
3220
|
+
for (unsigned int i = 0; i < files.count; i++) RL_FREE(files.paths[i]);
|
|
2978
3221
|
|
|
2979
|
-
RL_FREE(
|
|
3222
|
+
RL_FREE(files.paths);
|
|
2980
3223
|
|
|
2981
3224
|
CORE.Window.dropFileCount = 0;
|
|
3225
|
+
CORE.Window.dropFilepaths = NULL;
|
|
2982
3226
|
}
|
|
2983
3227
|
}
|
|
2984
3228
|
|
|
@@ -2997,8 +3241,8 @@ long GetFileModTime(const char *fileName)
|
|
|
2997
3241
|
return 0;
|
|
2998
3242
|
}
|
|
2999
3243
|
|
|
3000
|
-
// Compress data (DEFLATE
|
|
3001
|
-
unsigned char *CompressData(unsigned char *data, int
|
|
3244
|
+
// Compress data (DEFLATE algorithm)
|
|
3245
|
+
unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize)
|
|
3002
3246
|
{
|
|
3003
3247
|
#define COMPRESSION_QUALITY_DEFLATE 8
|
|
3004
3248
|
|
|
@@ -3007,40 +3251,40 @@ unsigned char *CompressData(unsigned char *data, int dataLength, int *compDataLe
|
|
|
3007
3251
|
#if defined(SUPPORT_COMPRESSION_API)
|
|
3008
3252
|
// Compress data and generate a valid DEFLATE stream
|
|
3009
3253
|
struct sdefl sdefl = { 0 };
|
|
3010
|
-
int bounds = sdefl_bound(
|
|
3254
|
+
int bounds = sdefl_bound(dataSize);
|
|
3011
3255
|
compData = (unsigned char *)RL_CALLOC(bounds, 1);
|
|
3012
|
-
*
|
|
3256
|
+
*compDataSize = sdeflate(&sdefl, compData, data, dataSize, COMPRESSION_QUALITY_DEFLATE); // Compression level 8, same as stbwi
|
|
3013
3257
|
|
|
3014
|
-
TraceLog(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i",
|
|
3258
|
+
TraceLog(LOG_INFO, "SYSTEM: Compress data: Original size: %i -> Comp. size: %i", dataSize, *compDataSize);
|
|
3015
3259
|
#endif
|
|
3016
3260
|
|
|
3017
3261
|
return compData;
|
|
3018
3262
|
}
|
|
3019
3263
|
|
|
3020
|
-
// Decompress data (DEFLATE
|
|
3021
|
-
unsigned char *DecompressData(unsigned char *compData, int
|
|
3264
|
+
// Decompress data (DEFLATE algorithm)
|
|
3265
|
+
unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize)
|
|
3022
3266
|
{
|
|
3023
3267
|
unsigned char *data = NULL;
|
|
3024
3268
|
|
|
3025
3269
|
#if defined(SUPPORT_COMPRESSION_API)
|
|
3026
3270
|
// Decompress data from a valid DEFLATE stream
|
|
3027
3271
|
data = RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1);
|
|
3028
|
-
int length = sinflate(data, MAX_DECOMPRESSION_SIZE, compData,
|
|
3272
|
+
int length = sinflate(data, MAX_DECOMPRESSION_SIZE*1024*1024, compData, compDataSize);
|
|
3029
3273
|
unsigned char *temp = RL_REALLOC(data, length);
|
|
3030
3274
|
|
|
3031
3275
|
if (temp != NULL) data = temp;
|
|
3032
3276
|
else TRACELOG(LOG_WARNING, "SYSTEM: Failed to re-allocate required decompression memory");
|
|
3033
3277
|
|
|
3034
|
-
*
|
|
3278
|
+
*dataSize = length;
|
|
3035
3279
|
|
|
3036
|
-
TraceLog(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i",
|
|
3280
|
+
TraceLog(LOG_INFO, "SYSTEM: Decompress data: Comp. size: %i -> Original size: %i", compDataSize, *dataSize);
|
|
3037
3281
|
#endif
|
|
3038
3282
|
|
|
3039
3283
|
return data;
|
|
3040
3284
|
}
|
|
3041
3285
|
|
|
3042
3286
|
// Encode data to Base64 string
|
|
3043
|
-
char *EncodeDataBase64(const unsigned char *data, int
|
|
3287
|
+
char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize)
|
|
3044
3288
|
{
|
|
3045
3289
|
static const unsigned char base64encodeTable[] = {
|
|
3046
3290
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
|
@@ -3050,17 +3294,17 @@ char *EncodeDataBase64(const unsigned char *data, int dataLength, int *outputLen
|
|
|
3050
3294
|
|
|
3051
3295
|
static const int modTable[] = { 0, 2, 1 };
|
|
3052
3296
|
|
|
3053
|
-
*
|
|
3297
|
+
*outputSize = 4*((dataSize + 2)/3);
|
|
3054
3298
|
|
|
3055
|
-
char *encodedData = RL_MALLOC(*
|
|
3299
|
+
char *encodedData = RL_MALLOC(*outputSize);
|
|
3056
3300
|
|
|
3057
3301
|
if (encodedData == NULL) return NULL;
|
|
3058
3302
|
|
|
3059
|
-
for (int i = 0, j = 0; i <
|
|
3303
|
+
for (int i = 0, j = 0; i < dataSize;)
|
|
3060
3304
|
{
|
|
3061
|
-
unsigned int octetA = (i <
|
|
3062
|
-
unsigned int octetB = (i <
|
|
3063
|
-
unsigned int octetC = (i <
|
|
3305
|
+
unsigned int octetA = (i < dataSize)? (unsigned char)data[i++] : 0;
|
|
3306
|
+
unsigned int octetB = (i < dataSize)? (unsigned char)data[i++] : 0;
|
|
3307
|
+
unsigned int octetC = (i < dataSize)? (unsigned char)data[i++] : 0;
|
|
3064
3308
|
|
|
3065
3309
|
unsigned int triple = (octetA << 0x10) + (octetB << 0x08) + octetC;
|
|
3066
3310
|
|
|
@@ -3070,13 +3314,13 @@ char *EncodeDataBase64(const unsigned char *data, int dataLength, int *outputLen
|
|
|
3070
3314
|
encodedData[j++] = base64encodeTable[(triple >> 0*6) & 0x3F];
|
|
3071
3315
|
}
|
|
3072
3316
|
|
|
3073
|
-
for (int i = 0; i < modTable[
|
|
3317
|
+
for (int i = 0; i < modTable[dataSize%3]; i++) encodedData[*outputSize - 1 - i] = '='; // Padding character
|
|
3074
3318
|
|
|
3075
3319
|
return encodedData;
|
|
3076
3320
|
}
|
|
3077
3321
|
|
|
3078
3322
|
// Decode Base64 string data
|
|
3079
|
-
unsigned char *DecodeDataBase64(unsigned char *data, int *
|
|
3323
|
+
unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
|
|
3080
3324
|
{
|
|
3081
3325
|
static const unsigned char base64decodeTable[] = {
|
|
3082
3326
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
@@ -3086,21 +3330,21 @@ unsigned char *DecodeDataBase64(unsigned char *data, int *outputLength)
|
|
|
3086
3330
|
};
|
|
3087
3331
|
|
|
3088
3332
|
// Get output size of Base64 input data
|
|
3089
|
-
int
|
|
3333
|
+
int outSize = 0;
|
|
3090
3334
|
for (int i = 0; data[4*i] != 0; i++)
|
|
3091
3335
|
{
|
|
3092
3336
|
if (data[4*i + 3] == '=')
|
|
3093
3337
|
{
|
|
3094
|
-
if (data[4*i + 2] == '=')
|
|
3095
|
-
else
|
|
3338
|
+
if (data[4*i + 2] == '=') outSize += 1;
|
|
3339
|
+
else outSize += 2;
|
|
3096
3340
|
}
|
|
3097
|
-
else
|
|
3341
|
+
else outSize += 3;
|
|
3098
3342
|
}
|
|
3099
3343
|
|
|
3100
3344
|
// Allocate memory to store decoded Base64 data
|
|
3101
|
-
unsigned char *decodedData = (unsigned char *)RL_MALLOC(
|
|
3345
|
+
unsigned char *decodedData = (unsigned char *)RL_MALLOC(outSize);
|
|
3102
3346
|
|
|
3103
|
-
for (int i = 0; i <
|
|
3347
|
+
for (int i = 0; i < outSize/3; i++)
|
|
3104
3348
|
{
|
|
3105
3349
|
unsigned char a = base64decodeTable[(int)data[4*i]];
|
|
3106
3350
|
unsigned char b = base64decodeTable[(int)data[4*i + 1]];
|
|
@@ -3112,131 +3356,27 @@ unsigned char *DecodeDataBase64(unsigned char *data, int *outputLength)
|
|
|
3112
3356
|
decodedData[3*i + 2] = (c << 6) | d;
|
|
3113
3357
|
}
|
|
3114
3358
|
|
|
3115
|
-
if (
|
|
3359
|
+
if (outSize%3 == 1)
|
|
3116
3360
|
{
|
|
3117
|
-
int n =
|
|
3361
|
+
int n = outSize/3;
|
|
3118
3362
|
unsigned char a = base64decodeTable[(int)data[4*n]];
|
|
3119
3363
|
unsigned char b = base64decodeTable[(int)data[4*n + 1]];
|
|
3120
|
-
decodedData[
|
|
3364
|
+
decodedData[outSize - 1] = (a << 2) | (b >> 4);
|
|
3121
3365
|
}
|
|
3122
|
-
else if (
|
|
3366
|
+
else if (outSize%3 == 2)
|
|
3123
3367
|
{
|
|
3124
|
-
int n =
|
|
3368
|
+
int n = outSize/3;
|
|
3125
3369
|
unsigned char a = base64decodeTable[(int)data[4*n]];
|
|
3126
3370
|
unsigned char b = base64decodeTable[(int)data[4*n + 1]];
|
|
3127
3371
|
unsigned char c = base64decodeTable[(int)data[4*n + 2]];
|
|
3128
|
-
decodedData[
|
|
3129
|
-
decodedData[
|
|
3372
|
+
decodedData[outSize - 2] = (a << 2) | (b >> 4);
|
|
3373
|
+
decodedData[outSize - 1] = (b << 4) | (c >> 2);
|
|
3130
3374
|
}
|
|
3131
3375
|
|
|
3132
|
-
*
|
|
3376
|
+
*outputSize = outSize;
|
|
3133
3377
|
return decodedData;
|
|
3134
3378
|
}
|
|
3135
3379
|
|
|
3136
|
-
// Save integer value to storage file (to defined position)
|
|
3137
|
-
// NOTE: Storage positions is directly related to file memory layout (4 bytes each integer)
|
|
3138
|
-
bool SaveStorageValue(unsigned int position, int value)
|
|
3139
|
-
{
|
|
3140
|
-
bool success = false;
|
|
3141
|
-
|
|
3142
|
-
#if defined(SUPPORT_DATA_STORAGE)
|
|
3143
|
-
char path[512] = { 0 };
|
|
3144
|
-
strcpy(path, TextFormat("%s/%s", CORE.Storage.basePath, STORAGE_DATA_FILE));
|
|
3145
|
-
|
|
3146
|
-
unsigned int dataSize = 0;
|
|
3147
|
-
unsigned int newDataSize = 0;
|
|
3148
|
-
unsigned char *fileData = LoadFileData(path, &dataSize);
|
|
3149
|
-
unsigned char *newFileData = NULL;
|
|
3150
|
-
|
|
3151
|
-
if (fileData != NULL)
|
|
3152
|
-
{
|
|
3153
|
-
if (dataSize <= (position*sizeof(int)))
|
|
3154
|
-
{
|
|
3155
|
-
// Increase data size up to position and store value
|
|
3156
|
-
newDataSize = (position + 1)*sizeof(int);
|
|
3157
|
-
newFileData = (unsigned char *)RL_REALLOC(fileData, newDataSize);
|
|
3158
|
-
|
|
3159
|
-
if (newFileData != NULL)
|
|
3160
|
-
{
|
|
3161
|
-
// RL_REALLOC succeded
|
|
3162
|
-
int *dataPtr = (int *)newFileData;
|
|
3163
|
-
dataPtr[position] = value;
|
|
3164
|
-
}
|
|
3165
|
-
else
|
|
3166
|
-
{
|
|
3167
|
-
// RL_REALLOC failed
|
|
3168
|
-
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to realloc data (%u), position in bytes (%u) bigger than actual file size", path, dataSize, position*sizeof(int));
|
|
3169
|
-
|
|
3170
|
-
// We store the old size of the file
|
|
3171
|
-
newFileData = fileData;
|
|
3172
|
-
newDataSize = dataSize;
|
|
3173
|
-
}
|
|
3174
|
-
}
|
|
3175
|
-
else
|
|
3176
|
-
{
|
|
3177
|
-
// Store the old size of the file
|
|
3178
|
-
newFileData = fileData;
|
|
3179
|
-
newDataSize = dataSize;
|
|
3180
|
-
|
|
3181
|
-
// Replace value on selected position
|
|
3182
|
-
int *dataPtr = (int *)newFileData;
|
|
3183
|
-
dataPtr[position] = value;
|
|
3184
|
-
}
|
|
3185
|
-
|
|
3186
|
-
success = SaveFileData(path, newFileData, newDataSize);
|
|
3187
|
-
RL_FREE(newFileData);
|
|
3188
|
-
|
|
3189
|
-
TRACELOG(LOG_INFO, "FILEIO: [%s] Saved storage value: %i", path, value);
|
|
3190
|
-
}
|
|
3191
|
-
else
|
|
3192
|
-
{
|
|
3193
|
-
TRACELOG(LOG_INFO, "FILEIO: [%s] File created successfully", path);
|
|
3194
|
-
|
|
3195
|
-
dataSize = (position + 1)*sizeof(int);
|
|
3196
|
-
fileData = (unsigned char *)RL_MALLOC(dataSize);
|
|
3197
|
-
int *dataPtr = (int *)fileData;
|
|
3198
|
-
dataPtr[position] = value;
|
|
3199
|
-
|
|
3200
|
-
success = SaveFileData(path, fileData, dataSize);
|
|
3201
|
-
UnloadFileData(fileData);
|
|
3202
|
-
|
|
3203
|
-
TRACELOG(LOG_INFO, "FILEIO: [%s] Saved storage value: %i", path, value);
|
|
3204
|
-
}
|
|
3205
|
-
#endif
|
|
3206
|
-
|
|
3207
|
-
return success;
|
|
3208
|
-
}
|
|
3209
|
-
|
|
3210
|
-
// Load integer value from storage file (from defined position)
|
|
3211
|
-
// NOTE: If requested position could not be found, value 0 is returned
|
|
3212
|
-
int LoadStorageValue(unsigned int position)
|
|
3213
|
-
{
|
|
3214
|
-
int value = 0;
|
|
3215
|
-
|
|
3216
|
-
#if defined(SUPPORT_DATA_STORAGE)
|
|
3217
|
-
char path[512] = { 0 };
|
|
3218
|
-
strcpy(path, TextFormat("%s/%s", CORE.Storage.basePath, STORAGE_DATA_FILE));
|
|
3219
|
-
|
|
3220
|
-
unsigned int dataSize = 0;
|
|
3221
|
-
unsigned char *fileData = LoadFileData(path, &dataSize);
|
|
3222
|
-
|
|
3223
|
-
if (fileData != NULL)
|
|
3224
|
-
{
|
|
3225
|
-
if (dataSize < (position*4)) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to find storage position: %i", path, position);
|
|
3226
|
-
else
|
|
3227
|
-
{
|
|
3228
|
-
int *dataPtr = (int *)fileData;
|
|
3229
|
-
value = dataPtr[position];
|
|
3230
|
-
}
|
|
3231
|
-
|
|
3232
|
-
UnloadFileData(fileData);
|
|
3233
|
-
|
|
3234
|
-
TRACELOG(LOG_INFO, "FILEIO: [%s] Loaded storage value: %i", path, value);
|
|
3235
|
-
}
|
|
3236
|
-
#endif
|
|
3237
|
-
return value;
|
|
3238
|
-
}
|
|
3239
|
-
|
|
3240
3380
|
// Open URL with default system browser (if available)
|
|
3241
3381
|
// NOTE: This function is only safe to use if you control the URL given.
|
|
3242
3382
|
// A user could craft a malicious string performing another action.
|
|
@@ -3255,19 +3395,43 @@ void OpenURL(const char *url)
|
|
|
3255
3395
|
#if defined(PLATFORM_DESKTOP)
|
|
3256
3396
|
char *cmd = (char *)RL_CALLOC(strlen(url) + 10, sizeof(char));
|
|
3257
3397
|
#if defined(_WIN32)
|
|
3258
|
-
sprintf(cmd, "explorer %s", url);
|
|
3398
|
+
sprintf(cmd, "explorer \"%s\"", url);
|
|
3259
3399
|
#endif
|
|
3260
|
-
#if defined(__linux__) || defined(__FreeBSD__)
|
|
3400
|
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
|
3261
3401
|
sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser
|
|
3262
3402
|
#endif
|
|
3263
3403
|
#if defined(__APPLE__)
|
|
3264
3404
|
sprintf(cmd, "open '%s'", url);
|
|
3265
3405
|
#endif
|
|
3266
|
-
system(cmd);
|
|
3406
|
+
int result = system(cmd);
|
|
3407
|
+
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
|
|
3267
3408
|
RL_FREE(cmd);
|
|
3268
3409
|
#endif
|
|
3269
3410
|
#if defined(PLATFORM_WEB)
|
|
3270
3411
|
emscripten_run_script(TextFormat("window.open('%s', '_blank')", url));
|
|
3412
|
+
#endif
|
|
3413
|
+
#if defined(PLATFORM_ANDROID)
|
|
3414
|
+
JNIEnv *env = NULL;
|
|
3415
|
+
JavaVM *vm = CORE.Android.app->activity->vm;
|
|
3416
|
+
(*vm)->AttachCurrentThread(vm, &env, NULL);
|
|
3417
|
+
|
|
3418
|
+
jstring urlString = (*env)->NewStringUTF(env, url);
|
|
3419
|
+
jclass uriClass = (*env)->FindClass(env, "android/net/Uri");
|
|
3420
|
+
jmethodID uriParse = (*env)->GetStaticMethodID(env, uriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;");
|
|
3421
|
+
jobject uri = (*env)->CallStaticObjectMethod(env, uriClass, uriParse, urlString);
|
|
3422
|
+
|
|
3423
|
+
jclass intentClass = (*env)->FindClass(env, "android/content/Intent");
|
|
3424
|
+
jfieldID actionViewId = (*env)->GetStaticFieldID(env, intentClass, "ACTION_VIEW", "Ljava/lang/String;");
|
|
3425
|
+
jobject actionView = (*env)->GetStaticObjectField(env, intentClass, actionViewId);
|
|
3426
|
+
jmethodID newIntent = (*env)->GetMethodID(env, intentClass, "<init>", "(Ljava/lang/String;Landroid/net/Uri;)V");
|
|
3427
|
+
jobject intent = (*env)->AllocObject(env, intentClass);
|
|
3428
|
+
|
|
3429
|
+
(*env)->CallVoidMethod(env, intent, newIntent, actionView, uri);
|
|
3430
|
+
jclass activityClass = (*env)->FindClass(env, "android/app/Activity");
|
|
3431
|
+
jmethodID startActivity = (*env)->GetMethodID(env, activityClass, "startActivity", "(Landroid/content/Intent;)V");
|
|
3432
|
+
(*env)->CallVoidMethod(env, CORE.Android.app->activity->clazz, startActivity, intent);
|
|
3433
|
+
|
|
3434
|
+
(*vm)->DetachCurrentThread(vm);
|
|
3271
3435
|
#endif
|
|
3272
3436
|
}
|
|
3273
3437
|
}
|
|
@@ -3594,14 +3758,24 @@ void SetMouseScale(float scaleX, float scaleY)
|
|
|
3594
3758
|
// Get mouse wheel movement Y
|
|
3595
3759
|
float GetMouseWheelMove(void)
|
|
3596
3760
|
{
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
#
|
|
3600
|
-
|
|
3601
|
-
|
|
3761
|
+
float result = 0.0f;
|
|
3762
|
+
|
|
3763
|
+
#if !defined(PLATFORM_ANDROID)
|
|
3764
|
+
if (fabsf(CORE.Input.Mouse.currentWheelMove.x) > fabsf(CORE.Input.Mouse.currentWheelMove.y)) result = (float)CORE.Input.Mouse.currentWheelMove.x;
|
|
3765
|
+
else result = (float)CORE.Input.Mouse.currentWheelMove.y;
|
|
3602
3766
|
#endif
|
|
3603
3767
|
|
|
3604
|
-
return
|
|
3768
|
+
return result;
|
|
3769
|
+
}
|
|
3770
|
+
|
|
3771
|
+
// Get mouse wheel movement X/Y as a vector
|
|
3772
|
+
Vector2 GetMouseWheelMoveV(void)
|
|
3773
|
+
{
|
|
3774
|
+
Vector2 result = { 0 };
|
|
3775
|
+
|
|
3776
|
+
result = CORE.Input.Mouse.currentWheelMove;
|
|
3777
|
+
|
|
3778
|
+
return result;
|
|
3605
3779
|
}
|
|
3606
3780
|
|
|
3607
3781
|
// Set mouse cursor
|
|
@@ -3804,6 +3978,10 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
3804
3978
|
#endif
|
|
3805
3979
|
}
|
|
3806
3980
|
else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
|
|
3981
|
+
|
|
3982
|
+
// Mouse passthrough
|
|
3983
|
+
if ((CORE.Window.flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) > 0) glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
|
|
3984
|
+
else glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_FALSE);
|
|
3807
3985
|
#endif
|
|
3808
3986
|
|
|
3809
3987
|
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
|
|
@@ -3892,14 +4070,6 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
3892
4070
|
}
|
|
3893
4071
|
}
|
|
3894
4072
|
}
|
|
3895
|
-
|
|
3896
|
-
#if defined(PLATFORM_DESKTOP)
|
|
3897
|
-
// If we are windowed fullscreen, ensures that window does not minimize when focus is lost
|
|
3898
|
-
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
|
|
3899
|
-
{
|
|
3900
|
-
glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
|
|
3901
|
-
}
|
|
3902
|
-
#endif
|
|
3903
4073
|
TRACELOG(LOG_WARNING, "SYSTEM: Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
|
3904
4074
|
|
|
3905
4075
|
// NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,
|
|
@@ -3921,6 +4091,13 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
3921
4091
|
}
|
|
3922
4092
|
else
|
|
3923
4093
|
{
|
|
4094
|
+
#if defined(PLATFORM_DESKTOP)
|
|
4095
|
+
// If we are windowed fullscreen, ensures that window does not minimize when focus is lost
|
|
4096
|
+
if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
|
|
4097
|
+
{
|
|
4098
|
+
glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
|
|
4099
|
+
}
|
|
4100
|
+
#endif
|
|
3924
4101
|
// No-fullscreen window creation
|
|
3925
4102
|
CORE.Window.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
|
|
3926
4103
|
|
|
@@ -3978,7 +4155,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
3978
4155
|
glfwSwapInterval(1);
|
|
3979
4156
|
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");
|
|
3980
4157
|
}
|
|
3981
|
-
|
|
4158
|
+
|
|
3982
4159
|
int fbWidth = CORE.Window.screen.width;
|
|
3983
4160
|
int fbHeight = CORE.Window.screen.height;
|
|
3984
4161
|
|
|
@@ -4003,7 +4180,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
4003
4180
|
CORE.Window.render.height = fbHeight;
|
|
4004
4181
|
CORE.Window.currentFbo.width = fbWidth;
|
|
4005
4182
|
CORE.Window.currentFbo.height = fbHeight;
|
|
4006
|
-
|
|
4183
|
+
|
|
4007
4184
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
|
4008
4185
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
|
4009
4186
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
|
@@ -4042,11 +4219,13 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
4042
4219
|
#else
|
|
4043
4220
|
TRACELOG(LOG_INFO, "DISPLAY: No graphic card set, trying platform-gpu-card");
|
|
4044
4221
|
CORE.Window.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
|
|
4222
|
+
|
|
4045
4223
|
if ((-1 == CORE.Window.fd) || (drmModeGetResources(CORE.Window.fd) == NULL))
|
|
4046
4224
|
{
|
|
4047
4225
|
TRACELOG(LOG_INFO, "DISPLAY: Failed to open platform-gpu-card, trying card1");
|
|
4048
4226
|
CORE.Window.fd = open("/dev/dri/card1", O_RDWR); // Other Embedded
|
|
4049
4227
|
}
|
|
4228
|
+
|
|
4050
4229
|
if ((-1 == CORE.Window.fd) || (drmModeGetResources(CORE.Window.fd) == NULL))
|
|
4051
4230
|
{
|
|
4052
4231
|
TRACELOG(LOG_INFO, "DISPLAY: Failed to open graphic card1, trying card0");
|
|
@@ -4415,7 +4594,7 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
4415
4594
|
CORE.Window.render.height = CORE.Window.screen.height;
|
|
4416
4595
|
CORE.Window.currentFbo.width = CORE.Window.render.width;
|
|
4417
4596
|
CORE.Window.currentFbo.height = CORE.Window.render.height;
|
|
4418
|
-
|
|
4597
|
+
|
|
4419
4598
|
TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
|
|
4420
4599
|
TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
|
|
4421
4600
|
TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
|
|
@@ -4440,8 +4619,6 @@ static bool InitGraphicsDevice(int width, int height)
|
|
|
4440
4619
|
// NOTE: It updated CORE.Window.render.width and CORE.Window.render.height
|
|
4441
4620
|
SetupViewport(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height);
|
|
4442
4621
|
|
|
4443
|
-
ClearBackground(RAYWHITE); // Default background color for raylib games :P
|
|
4444
|
-
|
|
4445
4622
|
#if defined(PLATFORM_ANDROID)
|
|
4446
4623
|
CORE.Window.ready = true;
|
|
4447
4624
|
#endif
|
|
@@ -4581,49 +4758,46 @@ static void InitTimer(void)
|
|
|
4581
4758
|
CORE.Time.previous = GetTime(); // Get time as double
|
|
4582
4759
|
}
|
|
4583
4760
|
|
|
4584
|
-
// Wait for some
|
|
4761
|
+
// Wait for some time (stop program execution)
|
|
4585
4762
|
// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could
|
|
4586
4763
|
// take longer than expected... for that reason we use the busy wait loop
|
|
4587
4764
|
// Ref: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
|
|
4588
4765
|
// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timming on Win32!
|
|
4589
|
-
void WaitTime(
|
|
4766
|
+
void WaitTime(double seconds)
|
|
4590
4767
|
{
|
|
4591
|
-
#if defined(SUPPORT_BUSY_WAIT_LOOP)
|
|
4592
|
-
double
|
|
4593
|
-
|
|
4768
|
+
#if defined(SUPPORT_BUSY_WAIT_LOOP) || defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
|
4769
|
+
double destinationTime = GetTime() + seconds;
|
|
4770
|
+
#endif
|
|
4594
4771
|
|
|
4595
|
-
|
|
4596
|
-
while ((
|
|
4772
|
+
#if defined(SUPPORT_BUSY_WAIT_LOOP)
|
|
4773
|
+
while (GetTime() < destinationTime) { }
|
|
4597
4774
|
#else
|
|
4598
4775
|
#if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
|
4599
|
-
double
|
|
4600
|
-
|
|
4776
|
+
double sleepSeconds = seconds - seconds*0.05; // NOTE: We reserve a percentage of the time for busy waiting
|
|
4777
|
+
#else
|
|
4778
|
+
double sleepSeconds = seconds;
|
|
4601
4779
|
#endif
|
|
4602
4780
|
|
|
4603
4781
|
// System halt functions
|
|
4604
4782
|
#if defined(_WIN32)
|
|
4605
|
-
Sleep((unsigned
|
|
4783
|
+
Sleep((unsigned long)(sleepSeconds*1000.0));
|
|
4606
4784
|
#endif
|
|
4607
|
-
#if defined(__linux__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__)
|
|
4785
|
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
|
4608
4786
|
struct timespec req = { 0 };
|
|
4609
|
-
time_t sec =
|
|
4610
|
-
|
|
4787
|
+
time_t sec = sleepSeconds;
|
|
4788
|
+
long nsec = (sleepSeconds - sec)*1000000000L;
|
|
4611
4789
|
req.tv_sec = sec;
|
|
4612
|
-
req.tv_nsec =
|
|
4790
|
+
req.tv_nsec = nsec;
|
|
4613
4791
|
|
|
4614
4792
|
// NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated.
|
|
4615
4793
|
while (nanosleep(&req, &req) == -1) continue;
|
|
4616
4794
|
#endif
|
|
4617
4795
|
#if defined(__APPLE__)
|
|
4618
|
-
usleep(
|
|
4796
|
+
usleep(sleepSeconds*1000000.0);
|
|
4619
4797
|
#endif
|
|
4620
4798
|
|
|
4621
4799
|
#if defined(SUPPORT_PARTIALBUSY_WAIT_LOOP)
|
|
4622
|
-
|
|
4623
|
-
double currentTime = 0.0;
|
|
4624
|
-
|
|
4625
|
-
// Partial busy wait loop (only a fraction of the total wait time)
|
|
4626
|
-
while ((currentTime - previousTime) < busyWait/1000.0f) currentTime = GetTime();
|
|
4800
|
+
while (GetTime() < destinationTime) { }
|
|
4627
4801
|
#endif
|
|
4628
4802
|
#endif
|
|
4629
4803
|
}
|
|
@@ -4639,53 +4813,31 @@ void SwapScreenBuffer(void)
|
|
|
4639
4813
|
eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
|
|
4640
4814
|
|
|
4641
4815
|
#if defined(PLATFORM_DRM)
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
|
|
4645
|
-
abort();
|
|
4646
|
-
}
|
|
4816
|
+
|
|
4817
|
+
if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc) TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
|
|
4647
4818
|
|
|
4648
4819
|
struct gbm_bo *bo = gbm_surface_lock_front_buffer(CORE.Window.gbmSurface);
|
|
4649
|
-
if (!bo)
|
|
4650
|
-
{
|
|
4651
|
-
TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
|
|
4652
|
-
abort();
|
|
4653
|
-
}
|
|
4820
|
+
if (!bo) TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
|
|
4654
4821
|
|
|
4655
4822
|
uint32_t fb = 0;
|
|
4656
|
-
int result = drmModeAddFB(CORE.Window.fd, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay,
|
|
4657
|
-
|
|
4658
|
-
if (0 != result)
|
|
4659
|
-
{
|
|
4660
|
-
TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
|
|
4661
|
-
abort();
|
|
4662
|
-
}
|
|
4823
|
+
int result = drmModeAddFB(CORE.Window.fd, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay, CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay, 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, &fb);
|
|
4824
|
+
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
|
|
4663
4825
|
|
|
4664
|
-
result = drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, fb, 0, 0,
|
|
4665
|
-
|
|
4666
|
-
if (0 != result)
|
|
4667
|
-
{
|
|
4668
|
-
TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
|
|
4669
|
-
abort();
|
|
4670
|
-
}
|
|
4826
|
+
result = drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, fb, 0, 0, &CORE.Window.connector->connector_id, 1, &CORE.Window.connector->modes[CORE.Window.modeIndex]);
|
|
4827
|
+
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
|
|
4671
4828
|
|
|
4672
4829
|
if (CORE.Window.prevFB)
|
|
4673
4830
|
{
|
|
4674
4831
|
result = drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB);
|
|
4675
|
-
if (
|
|
4676
|
-
{
|
|
4677
|
-
TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
|
|
4678
|
-
abort();
|
|
4679
|
-
}
|
|
4832
|
+
if (result != 0) TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
|
|
4680
4833
|
}
|
|
4834
|
+
|
|
4681
4835
|
CORE.Window.prevFB = fb;
|
|
4682
4836
|
|
|
4683
|
-
if (CORE.Window.prevBO)
|
|
4684
|
-
{
|
|
4685
|
-
gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
|
|
4686
|
-
}
|
|
4837
|
+
if (CORE.Window.prevBO) gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
|
|
4687
4838
|
|
|
4688
4839
|
CORE.Window.prevBO = bo;
|
|
4840
|
+
|
|
4689
4841
|
#endif // PLATFORM_DRM
|
|
4690
4842
|
#endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM
|
|
4691
4843
|
}
|
|
@@ -4717,7 +4869,7 @@ void PollInputEvents(void)
|
|
|
4717
4869
|
|
|
4718
4870
|
// Register previous mouse states
|
|
4719
4871
|
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
|
4720
|
-
CORE.Input.Mouse.currentWheelMove = 0.0f;
|
|
4872
|
+
CORE.Input.Mouse.currentWheelMove = (Vector2){ 0.0f, 0.0f };
|
|
4721
4873
|
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++)
|
|
4722
4874
|
{
|
|
4723
4875
|
CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
|
|
@@ -4746,7 +4898,7 @@ void PollInputEvents(void)
|
|
|
4746
4898
|
|
|
4747
4899
|
// Register previous mouse wheel state
|
|
4748
4900
|
CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
|
|
4749
|
-
CORE.Input.Mouse.currentWheelMove = 0.0f;
|
|
4901
|
+
CORE.Input.Mouse.currentWheelMove = (Vector2){ 0.0f, 0.0f };
|
|
4750
4902
|
|
|
4751
4903
|
// Register previous mouse position
|
|
4752
4904
|
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
|
@@ -4754,7 +4906,7 @@ void PollInputEvents(void)
|
|
|
4754
4906
|
|
|
4755
4907
|
// Register previous touch states
|
|
4756
4908
|
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
|
|
4757
|
-
|
|
4909
|
+
|
|
4758
4910
|
// Reset touch positions
|
|
4759
4911
|
// TODO: It resets on PLATFORM_WEB the mouse position and not filled again until a move-event,
|
|
4760
4912
|
// so, if mouse is not moved it returns a (0, 0) position... this behaviour should be reviewed!
|
|
@@ -4833,8 +4985,8 @@ void PollInputEvents(void)
|
|
|
4833
4985
|
}
|
|
4834
4986
|
|
|
4835
4987
|
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)
|
|
4836
|
-
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.
|
|
4837
|
-
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.
|
|
4988
|
+
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f);
|
|
4989
|
+
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f);
|
|
4838
4990
|
|
|
4839
4991
|
CORE.Input.Gamepad.axisCount = GLFW_GAMEPAD_AXIS_LAST + 1;
|
|
4840
4992
|
}
|
|
@@ -4842,11 +4994,8 @@ void PollInputEvents(void)
|
|
|
4842
4994
|
|
|
4843
4995
|
CORE.Window.resizedLastFrame = false;
|
|
4844
4996
|
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
#else
|
|
4848
|
-
glfwPollEvents(); // Register keyboard/mouse events (callbacks)... and window events!
|
|
4849
|
-
#endif
|
|
4997
|
+
if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
|
|
4998
|
+
else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks)
|
|
4850
4999
|
#endif // PLATFORM_DESKTOP
|
|
4851
5000
|
|
|
4852
5001
|
#if defined(PLATFORM_WEB)
|
|
@@ -4958,45 +5107,102 @@ void PollInputEvents(void)
|
|
|
4958
5107
|
#endif
|
|
4959
5108
|
}
|
|
4960
5109
|
|
|
4961
|
-
|
|
4962
|
-
//
|
|
4963
|
-
|
|
5110
|
+
// Scan all files and directories in a base path
|
|
5111
|
+
// WARNING: files.paths[] must be previously allocated and
|
|
5112
|
+
// contain enough space to store all required paths
|
|
5113
|
+
static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const char *filter)
|
|
4964
5114
|
{
|
|
4965
|
-
|
|
4966
|
-
|
|
5115
|
+
static char path[MAX_FILEPATH_LENGTH] = { 0 };
|
|
5116
|
+
memset(path, 0, MAX_FILEPATH_LENGTH);
|
|
4967
5117
|
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
EM_JS(int, GetCanvasHeight, (), { return canvas.clientHeight; });
|
|
5118
|
+
struct dirent *dp = NULL;
|
|
5119
|
+
DIR *dir = opendir(basePath);
|
|
4971
5120
|
|
|
4972
|
-
|
|
4973
|
-
{
|
|
4974
|
-
|
|
4975
|
-
|
|
5121
|
+
if (dir != NULL)
|
|
5122
|
+
{
|
|
5123
|
+
while ((dp = readdir(dir)) != NULL)
|
|
5124
|
+
{
|
|
5125
|
+
if ((strcmp(dp->d_name, ".") != 0) &&
|
|
5126
|
+
(strcmp(dp->d_name, "..") != 0))
|
|
5127
|
+
{
|
|
5128
|
+
sprintf(path, "%s/%s", basePath, dp->d_name);
|
|
4976
5129
|
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
5130
|
+
if (filter != NULL)
|
|
5131
|
+
{
|
|
5132
|
+
if (IsFileExtension(path, filter))
|
|
5133
|
+
{
|
|
5134
|
+
strcpy(files->paths[files->count], path);
|
|
5135
|
+
files->count++;
|
|
5136
|
+
}
|
|
5137
|
+
}
|
|
5138
|
+
else
|
|
5139
|
+
{
|
|
5140
|
+
strcpy(files->paths[files->count], path);
|
|
5141
|
+
files->count++;
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
4982
5145
|
|
|
4983
|
-
|
|
5146
|
+
closedir(dir);
|
|
5147
|
+
}
|
|
5148
|
+
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath);
|
|
5149
|
+
}
|
|
4984
5150
|
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
5151
|
+
// Scan all files and directories recursively from a base path
|
|
5152
|
+
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter)
|
|
5153
|
+
{
|
|
5154
|
+
static char path[MAX_FILEPATH_LENGTH] = { 0 };
|
|
5155
|
+
memset(path, 0, MAX_FILEPATH_LENGTH);
|
|
4988
5156
|
|
|
4989
|
-
|
|
5157
|
+
struct dirent *dp = NULL;
|
|
5158
|
+
DIR *dir = opendir(basePath);
|
|
4990
5159
|
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
5160
|
+
if (dir != NULL)
|
|
5161
|
+
{
|
|
5162
|
+
while (((dp = readdir(dir)) != NULL) && (files->count < files->capacity))
|
|
5163
|
+
{
|
|
5164
|
+
if ((strcmp(dp->d_name, ".") != 0) && (strcmp(dp->d_name, "..") != 0))
|
|
5165
|
+
{
|
|
5166
|
+
// Construct new path from our base path
|
|
5167
|
+
sprintf(path, "%s/%s", basePath, dp->d_name);
|
|
4994
5168
|
|
|
4995
|
-
|
|
5169
|
+
if (IsPathFile(path))
|
|
5170
|
+
{
|
|
5171
|
+
if (filter != NULL)
|
|
5172
|
+
{
|
|
5173
|
+
if (IsFileExtension(path, filter))
|
|
5174
|
+
{
|
|
5175
|
+
strcpy(files->paths[files->count], path);
|
|
5176
|
+
files->count++;
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5179
|
+
else
|
|
5180
|
+
{
|
|
5181
|
+
strcpy(files->paths[files->count], path);
|
|
5182
|
+
files->count++;
|
|
5183
|
+
}
|
|
4996
5184
|
|
|
4997
|
-
|
|
5185
|
+
if (files->count >= files->capacity)
|
|
5186
|
+
{
|
|
5187
|
+
TRACELOG(LOG_WARNING, "FILEIO: Maximum filepath scan capacity reached (%i files)", files->capacity);
|
|
5188
|
+
break;
|
|
5189
|
+
}
|
|
5190
|
+
}
|
|
5191
|
+
else ScanDirectoryFilesRecursively(path, files, filter);
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
|
|
5195
|
+
closedir(dir);
|
|
5196
|
+
}
|
|
5197
|
+
else TRACELOG(LOG_WARNING, "FILEIO: Directory cannot be opened (%s)", basePath);
|
|
5198
|
+
}
|
|
5199
|
+
|
|
5200
|
+
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
|
5201
|
+
// GLFW3 Error Callback, runs on GLFW3 error
|
|
5202
|
+
static void ErrorCallback(int error, const char *description)
|
|
5203
|
+
{
|
|
5204
|
+
TRACELOG(LOG_WARNING, "GLFW: Error: %i Description: %s", error, description);
|
|
4998
5205
|
}
|
|
4999
|
-
#endif
|
|
5000
5206
|
|
|
5001
5207
|
// GLFW3 WindowSize Callback, runs when window is resizedLastFrame
|
|
5002
5208
|
// NOTE: Window resizing not allowed by default
|
|
@@ -5059,6 +5265,8 @@ static void WindowFocusCallback(GLFWwindow *window, int focused)
|
|
|
5059
5265
|
// GLFW3 Keyboard Callback, runs on key pressed
|
|
5060
5266
|
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
|
5061
5267
|
{
|
|
5268
|
+
if (key < 0) return; // Security check, macOS fn key generates -1
|
|
5269
|
+
|
|
5062
5270
|
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
|
|
5063
5271
|
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
|
|
5064
5272
|
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
|
|
@@ -5071,7 +5279,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
|
|
5071
5279
|
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
|
|
5072
5280
|
CORE.Input.Keyboard.keyPressedQueueCount++;
|
|
5073
5281
|
}
|
|
5074
|
-
|
|
5282
|
+
|
|
5075
5283
|
// Check the exit key to set close window
|
|
5076
5284
|
if ((key == CORE.Input.Keyboard.exitKey) && (action == GLFW_PRESS)) glfwSetWindowShouldClose(CORE.Window.handle, GLFW_TRUE);
|
|
5077
5285
|
|
|
@@ -5103,7 +5311,8 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
|
|
5103
5311
|
gifRecording = true;
|
|
5104
5312
|
gifFrameCounter = 0;
|
|
5105
5313
|
|
|
5106
|
-
|
|
5314
|
+
Vector2 scale = GetWindowScaleDPI();
|
|
5315
|
+
msf_gif_begin(&gifState, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y));
|
|
5107
5316
|
screenshotCounter++;
|
|
5108
5317
|
|
|
5109
5318
|
TRACELOG(LOG_INFO, "SYSTEM: Start animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter));
|
|
@@ -5221,11 +5430,10 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
|
|
|
5221
5430
|
#endif
|
|
5222
5431
|
}
|
|
5223
5432
|
|
|
5224
|
-
// GLFW3
|
|
5433
|
+
// GLFW3 Scrolling Callback, runs on mouse wheel
|
|
5225
5434
|
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset)
|
|
5226
5435
|
{
|
|
5227
|
-
|
|
5228
|
-
else CORE.Input.Mouse.currentWheelMove = (float)yoffset;
|
|
5436
|
+
CORE.Input.Mouse.currentWheelMove = (Vector2){ (float)xoffset, (float)yoffset };
|
|
5229
5437
|
}
|
|
5230
5438
|
|
|
5231
5439
|
// GLFW3 CursorEnter Callback, when cursor enters the window
|
|
@@ -5236,21 +5444,28 @@ static void CursorEnterCallback(GLFWwindow *window, int enter)
|
|
|
5236
5444
|
}
|
|
5237
5445
|
|
|
5238
5446
|
// GLFW3 Window Drop Callback, runs when drop files into window
|
|
5239
|
-
// NOTE: Paths are stored in dynamic memory for further retrieval
|
|
5240
|
-
// Everytime new files are dropped, old ones are discarded
|
|
5241
5447
|
static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)
|
|
5242
5448
|
{
|
|
5243
|
-
|
|
5449
|
+
// In case previous dropped filepaths have not been freed, we free them
|
|
5450
|
+
if (CORE.Window.dropFileCount > 0)
|
|
5451
|
+
{
|
|
5452
|
+
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilepaths[i]);
|
|
5244
5453
|
|
|
5245
|
-
|
|
5454
|
+
RL_FREE(CORE.Window.dropFilepaths);
|
|
5246
5455
|
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
CORE.Window.dropFilesPath[i] = (char *)RL_MALLOC(MAX_FILEPATH_LENGTH*sizeof(char));
|
|
5250
|
-
strcpy(CORE.Window.dropFilesPath[i], paths[i]);
|
|
5456
|
+
CORE.Window.dropFileCount = 0;
|
|
5457
|
+
CORE.Window.dropFilepaths = NULL;
|
|
5251
5458
|
}
|
|
5252
5459
|
|
|
5460
|
+
// WARNING: Paths are freed by GLFW when the callback returns, we must keep an internal copy
|
|
5253
5461
|
CORE.Window.dropFileCount = count;
|
|
5462
|
+
CORE.Window.dropFilepaths = (char **)RL_CALLOC(CORE.Window.dropFileCount, sizeof(char *));
|
|
5463
|
+
|
|
5464
|
+
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
|
|
5465
|
+
{
|
|
5466
|
+
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
|
5467
|
+
strcpy(CORE.Window.dropFilepaths[i], paths[i]);
|
|
5468
|
+
}
|
|
5254
5469
|
}
|
|
5255
5470
|
#endif
|
|
5256
5471
|
|
|
@@ -5296,13 +5511,15 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
|
|
|
5296
5511
|
// Initialize random seed
|
|
5297
5512
|
srand((unsigned int)time(NULL));
|
|
5298
5513
|
|
|
5299
|
-
#if defined(SUPPORT_DEFAULT_FONT)
|
|
5514
|
+
#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT)
|
|
5300
5515
|
// Load default font
|
|
5301
|
-
//
|
|
5516
|
+
// WARNING: External function: Module required: rtext
|
|
5302
5517
|
LoadFontDefault();
|
|
5303
5518
|
Rectangle rec = GetFontDefault().recs[95];
|
|
5304
5519
|
// NOTE: We setup a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
|
|
5305
|
-
|
|
5520
|
+
#if defined(SUPPORT_MODULE_RSHAPES)
|
|
5521
|
+
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes
|
|
5522
|
+
#endif
|
|
5306
5523
|
#endif
|
|
5307
5524
|
|
|
5308
5525
|
// TODO: GPU assets reload in case of lost focus (lost context)
|
|
@@ -5485,11 +5702,82 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|
|
5485
5702
|
#endif
|
|
5486
5703
|
|
|
5487
5704
|
#if defined(PLATFORM_WEB)
|
|
5705
|
+
// Register fullscreen change events
|
|
5706
|
+
static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
|
|
5707
|
+
{
|
|
5708
|
+
// TODO: Implement EmscriptenFullscreenChangeCallback()?
|
|
5709
|
+
|
|
5710
|
+
return 1; // The event was consumed by the callback handler
|
|
5711
|
+
}
|
|
5712
|
+
|
|
5713
|
+
// Register window resize event
|
|
5714
|
+
static EM_BOOL EmscriptenWindowResizedCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
|
|
5715
|
+
{
|
|
5716
|
+
// TODO: Implement EmscriptenWindowResizedCallback()?
|
|
5717
|
+
|
|
5718
|
+
return 1; // The event was consumed by the callback handler
|
|
5719
|
+
}
|
|
5720
|
+
|
|
5721
|
+
EM_JS(int, GetCanvasWidth, (), { return canvas.clientWidth; });
|
|
5722
|
+
EM_JS(int, GetCanvasHeight, (), { return canvas.clientHeight; });
|
|
5723
|
+
|
|
5724
|
+
// Register DOM element resize event
|
|
5725
|
+
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData)
|
|
5726
|
+
{
|
|
5727
|
+
// Don't resize non-resizeable windows
|
|
5728
|
+
if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) return 1;
|
|
5729
|
+
|
|
5730
|
+
// This event is called whenever the window changes sizes,
|
|
5731
|
+
// so the size of the canvas object is explicitly retrieved below
|
|
5732
|
+
int width = GetCanvasWidth();
|
|
5733
|
+
int height = GetCanvasHeight();
|
|
5734
|
+
emscripten_set_canvas_element_size("#canvas",width,height);
|
|
5735
|
+
|
|
5736
|
+
SetupViewport(width, height); // Reset viewport and projection matrix for new size
|
|
5737
|
+
|
|
5738
|
+
CORE.Window.currentFbo.width = width;
|
|
5739
|
+
CORE.Window.currentFbo.height = height;
|
|
5740
|
+
CORE.Window.resizedLastFrame = true;
|
|
5741
|
+
|
|
5742
|
+
if (IsWindowFullscreen()) return 1;
|
|
5743
|
+
|
|
5744
|
+
// Set current screen size
|
|
5745
|
+
CORE.Window.screen.width = width;
|
|
5746
|
+
CORE.Window.screen.height = height;
|
|
5747
|
+
|
|
5748
|
+
// NOTE: Postprocessing texture is not scaled to new size
|
|
5749
|
+
|
|
5750
|
+
return 0;
|
|
5751
|
+
}
|
|
5752
|
+
|
|
5488
5753
|
// Register mouse input events
|
|
5489
5754
|
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
|
|
5490
5755
|
{
|
|
5491
5756
|
// This is only for registering mouse click events with emscripten and doesn't need to do anything
|
|
5492
|
-
|
|
5757
|
+
|
|
5758
|
+
return 1; // The event was consumed by the callback handler
|
|
5759
|
+
}
|
|
5760
|
+
|
|
5761
|
+
// Register connected/disconnected gamepads events
|
|
5762
|
+
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
|
|
5763
|
+
{
|
|
5764
|
+
/*
|
|
5765
|
+
TRACELOGD("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"",
|
|
5766
|
+
eventType != 0? emscripten_event_type_to_string(eventType) : "Gamepad state",
|
|
5767
|
+
gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping);
|
|
5768
|
+
|
|
5769
|
+
for (int i = 0; i < gamepadEvent->numAxes; ++i) TRACELOGD("Axis %d: %g", i, gamepadEvent->axis[i]);
|
|
5770
|
+
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
|
|
5771
|
+
*/
|
|
5772
|
+
|
|
5773
|
+
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS))
|
|
5774
|
+
{
|
|
5775
|
+
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
|
5776
|
+
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index],"%s",gamepadEvent->id);
|
|
5777
|
+
}
|
|
5778
|
+
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
|
5779
|
+
|
|
5780
|
+
return 1; // The event was consumed by the callback handler
|
|
5493
5781
|
}
|
|
5494
5782
|
|
|
5495
5783
|
// Register touch input events
|
|
@@ -5542,29 +5830,7 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
|
|
|
5542
5830
|
ProcessGestureEvent(gestureEvent);
|
|
5543
5831
|
#endif
|
|
5544
5832
|
|
|
5545
|
-
return 1;
|
|
5546
|
-
}
|
|
5547
|
-
|
|
5548
|
-
// Register connected/disconnected gamepads events
|
|
5549
|
-
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
|
|
5550
|
-
{
|
|
5551
|
-
/*
|
|
5552
|
-
TRACELOGD("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"",
|
|
5553
|
-
eventType != 0? emscripten_event_type_to_string(eventType) : "Gamepad state",
|
|
5554
|
-
gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping);
|
|
5555
|
-
|
|
5556
|
-
for (int i = 0; i < gamepadEvent->numAxes; ++i) TRACELOGD("Axis %d: %g", i, gamepadEvent->axis[i]);
|
|
5557
|
-
for (int i = 0; i < gamepadEvent->numButtons; ++i) TRACELOGD("Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
|
|
5558
|
-
*/
|
|
5559
|
-
|
|
5560
|
-
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS))
|
|
5561
|
-
{
|
|
5562
|
-
CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
|
|
5563
|
-
sprintf(CORE.Input.Gamepad.name[gamepadEvent->index],"%s",gamepadEvent->id);
|
|
5564
|
-
}
|
|
5565
|
-
else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
|
|
5566
|
-
|
|
5567
|
-
return 0;
|
|
5833
|
+
return 1; // The event was consumed by the callback handler
|
|
5568
5834
|
}
|
|
5569
5835
|
#endif
|
|
5570
5836
|
|
|
@@ -5633,8 +5899,8 @@ static void ProcessKeyboard(void)
|
|
|
5633
5899
|
#define MAX_KEYBUFFER_SIZE 32 // Max size in bytes to read
|
|
5634
5900
|
|
|
5635
5901
|
// Keyboard input polling (fill keys[256] array with status)
|
|
5636
|
-
int bufferByteCount = 0;
|
|
5637
|
-
char keysBuffer[MAX_KEYBUFFER_SIZE]; // Max keys to be read at a time
|
|
5902
|
+
int bufferByteCount = 0; // Bytes available on the buffer
|
|
5903
|
+
char keysBuffer[MAX_KEYBUFFER_SIZE] = { 0 }; // Max keys to be read at a time
|
|
5638
5904
|
|
|
5639
5905
|
// Read availables keycodes from stdin
|
|
5640
5906
|
bufferByteCount = read(STDIN_FILENO, keysBuffer, MAX_KEYBUFFER_SIZE); // POSIX system call
|
|
@@ -5765,7 +6031,8 @@ static void InitEvdevInput(void)
|
|
|
5765
6031
|
{
|
|
5766
6032
|
while ((entity = readdir(directory)) != NULL)
|
|
5767
6033
|
{
|
|
5768
|
-
if (strncmp("event", entity->d_name, strlen("event")) == 0)
|
|
6034
|
+
if ((strncmp("event", entity->d_name, strlen("event")) == 0) || // Search for devices named "event*"
|
|
6035
|
+
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
|
|
5769
6036
|
{
|
|
5770
6037
|
sprintf(path, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
|
|
5771
6038
|
ConfigureEvdevDevice(path); // Configure the device if appropriate
|
|
@@ -5828,7 +6095,7 @@ static void ConfigureEvdevDevice(char *device)
|
|
|
5828
6095
|
fd = open(device, O_RDONLY | O_NONBLOCK);
|
|
5829
6096
|
if (fd < 0)
|
|
5830
6097
|
{
|
|
5831
|
-
TRACELOG(LOG_WARNING, "RPI: Failed to open input device %s", device);
|
|
6098
|
+
TRACELOG(LOG_WARNING, "RPI: Failed to open input device: %s", device);
|
|
5832
6099
|
return;
|
|
5833
6100
|
}
|
|
5834
6101
|
worker->fd = fd;
|
|
@@ -5842,6 +6109,7 @@ static void ConfigureEvdevDevice(char *device)
|
|
|
5842
6109
|
{
|
|
5843
6110
|
if (sscanf(ptrDevName, "t%d", &devNum) == 1) worker->eventNum = devNum;
|
|
5844
6111
|
}
|
|
6112
|
+
else worker->eventNum = 0; // TODO: HACK: Grab number for mouse0 device!
|
|
5845
6113
|
|
|
5846
6114
|
// At this point we have a connection to the device, but we don't yet know what the device is.
|
|
5847
6115
|
// It could be many things, even as simple as a power button...
|
|
@@ -5925,7 +6193,7 @@ static void ConfigureEvdevDevice(char *device)
|
|
|
5925
6193
|
|
|
5926
6194
|
// Decide what to do with the device
|
|
5927
6195
|
//-------------------------------------------------------------------------------------------------------
|
|
5928
|
-
if (worker->isKeyboard && CORE.Input.Keyboard.fd == -1)
|
|
6196
|
+
if (worker->isKeyboard && (CORE.Input.Keyboard.fd == -1))
|
|
5929
6197
|
{
|
|
5930
6198
|
// Use the first keyboard encountered. This assumes that a device that says it's a keyboard is just a
|
|
5931
6199
|
// keyboard. The keyboard is polled synchronously, whereas other input devices are polled in separate
|
|
@@ -6089,7 +6357,7 @@ static void *EventThread(void *arg)
|
|
|
6089
6357
|
gestureUpdate = true;
|
|
6090
6358
|
}
|
|
6091
6359
|
|
|
6092
|
-
if (event.code == REL_WHEEL) CORE.Input.Mouse.currentWheelMove += event.value;
|
|
6360
|
+
if (event.code == REL_WHEEL) CORE.Input.Mouse.currentWheelMove.y += event.value;
|
|
6093
6361
|
}
|
|
6094
6362
|
|
|
6095
6363
|
// Absolute movement parsing
|
|
@@ -6220,7 +6488,7 @@ static void *EventThread(void *arg)
|
|
|
6220
6488
|
#endif
|
|
6221
6489
|
}
|
|
6222
6490
|
|
|
6223
|
-
WaitTime(
|
|
6491
|
+
WaitTime(0.005); // Sleep for 5ms to avoid hogging CPU time
|
|
6224
6492
|
}
|
|
6225
6493
|
|
|
6226
6494
|
close(worker->fd);
|
|
@@ -6237,7 +6505,7 @@ static void InitGamepad(void)
|
|
|
6237
6505
|
{
|
|
6238
6506
|
sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i);
|
|
6239
6507
|
|
|
6240
|
-
if ((CORE.Input.Gamepad.streamId[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0)
|
|
6508
|
+
if ((CORE.Input.Gamepad.streamId[i] = open(gamepadDev, O_RDONLY | O_NONBLOCK)) < 0)
|
|
6241
6509
|
{
|
|
6242
6510
|
// NOTE: Only show message for first gamepad
|
|
6243
6511
|
if (i == 0) TRACELOG(LOG_WARNING, "RPI: Failed to open Gamepad device, no gamepad available");
|
|
@@ -6308,7 +6576,7 @@ static void *GamepadThread(void *arg)
|
|
|
6308
6576
|
}
|
|
6309
6577
|
}
|
|
6310
6578
|
}
|
|
6311
|
-
else WaitTime(
|
|
6579
|
+
else WaitTime(0.001); // Sleep for 1 ms to avoid hogging CPU time
|
|
6312
6580
|
}
|
|
6313
6581
|
}
|
|
6314
6582
|
|
|
@@ -6376,7 +6644,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
|
|
6376
6644
|
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh,
|
|
6377
6645
|
(mode->flags & DRM_MODE_FLAG_INTERLACE) ? "interlaced" : "progressive");
|
|
6378
6646
|
|
|
6379
|
-
if ((mode->hdisplay < width) || (mode->vdisplay < height)
|
|
6647
|
+
if ((mode->hdisplay < width) || (mode->vdisplay < height))
|
|
6380
6648
|
{
|
|
6381
6649
|
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode is too small");
|
|
6382
6650
|
continue;
|
|
@@ -6388,23 +6656,22 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
|
|
6388
6656
|
continue;
|
|
6389
6657
|
}
|
|
6390
6658
|
|
|
6391
|
-
if (
|
|
6659
|
+
if (nearestIndex < 0)
|
|
6392
6660
|
{
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6661
|
+
nearestIndex = i;
|
|
6662
|
+
continue;
|
|
6663
|
+
}
|
|
6396
6664
|
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
continue;
|
|
6401
|
-
}
|
|
6665
|
+
const int widthDiff = abs(mode->hdisplay - width);
|
|
6666
|
+
const int heightDiff = abs(mode->vdisplay - height);
|
|
6667
|
+
const int fpsDiff = abs(mode->vrefresh - fps);
|
|
6402
6668
|
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6669
|
+
const int nearestWidthDiff = abs(CORE.Window.connector->modes[nearestIndex].hdisplay - width);
|
|
6670
|
+
const int nearestHeightDiff = abs(CORE.Window.connector->modes[nearestIndex].vdisplay - height);
|
|
6671
|
+
const int nearestFpsDiff = abs(CORE.Window.connector->modes[nearestIndex].vrefresh - fps);
|
|
6406
6672
|
|
|
6407
|
-
|
|
6673
|
+
if ((widthDiff < nearestWidthDiff) || (heightDiff < nearestHeightDiff) || (fpsDiff < nearestFpsDiff)) {
|
|
6674
|
+
nearestIndex = i;
|
|
6408
6675
|
}
|
|
6409
6676
|
}
|
|
6410
6677
|
|
|
@@ -6414,6 +6681,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
|
|
6414
6681
|
|
|
6415
6682
|
#if defined(SUPPORT_EVENTS_AUTOMATION)
|
|
6416
6683
|
// NOTE: Loading happens over AutomationEvent *events
|
|
6684
|
+
// TODO: This system should probably be redesigned
|
|
6417
6685
|
static void LoadAutomationEvents(const char *fileName)
|
|
6418
6686
|
{
|
|
6419
6687
|
//unsigned char fileId[4] = { 0 };
|
|
@@ -6576,12 +6844,13 @@ static void RecordAutomationEvent(unsigned int frame)
|
|
|
6576
6844
|
}
|
|
6577
6845
|
|
|
6578
6846
|
// INPUT_MOUSE_WHEEL_MOTION
|
|
6579
|
-
if ((int)CORE.Input.Mouse.currentWheelMove != (int)CORE.Input.Mouse.previousWheelMove)
|
|
6847
|
+
if (((int)CORE.Input.Mouse.currentWheelMove.x != (int)CORE.Input.Mouse.previousWheelMove.x) ||
|
|
6848
|
+
((int)CORE.Input.Mouse.currentWheelMove.y != (int)CORE.Input.Mouse.previousWheelMove.y))
|
|
6580
6849
|
{
|
|
6581
6850
|
events[eventCount].frame = frame;
|
|
6582
6851
|
events[eventCount].type = INPUT_MOUSE_WHEEL_MOTION;
|
|
6583
|
-
events[eventCount].params[0] = (int)CORE.Input.Mouse.currentWheelMove;
|
|
6584
|
-
events[eventCount].params[1] =
|
|
6852
|
+
events[eventCount].params[0] = (int)CORE.Input.Mouse.currentWheelMove.x;
|
|
6853
|
+
events[eventCount].params[1] = (int)CORE.Input.Mouse.currentWheelMove.y;;
|
|
6585
6854
|
events[eventCount].params[2] = 0;
|
|
6586
6855
|
|
|
6587
6856
|
TRACELOG(LOG_INFO, "[%i] INPUT_MOUSE_WHEEL_MOTION: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]);
|
|
@@ -6733,7 +7002,11 @@ static void PlayAutomationEvent(unsigned int frame)
|
|
|
6733
7002
|
CORE.Input.Mouse.currentPosition.x = (float)events[i].params[0];
|
|
6734
7003
|
CORE.Input.Mouse.currentPosition.y = (float)events[i].params[1];
|
|
6735
7004
|
} break;
|
|
6736
|
-
case INPUT_MOUSE_WHEEL_MOTION:
|
|
7005
|
+
case INPUT_MOUSE_WHEEL_MOTION: // param[0]: x delta, param[1]: y delta
|
|
7006
|
+
{
|
|
7007
|
+
CORE.Input.Mouse.currentWheelMove.x = (float)events[i].params[0]; break;
|
|
7008
|
+
CORE.Input.Mouse.currentWheelMove.y = (float)events[i].params[1]; break;
|
|
7009
|
+
} break;
|
|
6737
7010
|
case INPUT_TOUCH_UP: CORE.Input.Touch.currentTouchState[events[i].params[0]] = false; break; // param[0]: id
|
|
6738
7011
|
case INPUT_TOUCH_DOWN: CORE.Input.Touch.currentTouchState[events[i].params[0]] = true; break; // param[0]: id
|
|
6739
7012
|
case INPUT_TOUCH_POSITION: // param[0]: id, param[1]: x, param[2]: y
|
|
@@ -6770,3 +7043,34 @@ static void PlayAutomationEvent(unsigned int frame)
|
|
|
6770
7043
|
}
|
|
6771
7044
|
}
|
|
6772
7045
|
#endif
|
|
7046
|
+
|
|
7047
|
+
#if !defined(SUPPORT_MODULE_RTEXT)
|
|
7048
|
+
// Formatting of text with variables to 'embed'
|
|
7049
|
+
// WARNING: String returned will expire after this function is called MAX_TEXTFORMAT_BUFFERS times
|
|
7050
|
+
const char *TextFormat(const char *text, ...)
|
|
7051
|
+
{
|
|
7052
|
+
#ifndef MAX_TEXTFORMAT_BUFFERS
|
|
7053
|
+
#define MAX_TEXTFORMAT_BUFFERS 4 // Maximum number of static buffers for text formatting
|
|
7054
|
+
#endif
|
|
7055
|
+
#ifndef MAX_TEXT_BUFFER_LENGTH
|
|
7056
|
+
#define MAX_TEXT_BUFFER_LENGTH 1024 // Maximum size of static text buffer
|
|
7057
|
+
#endif
|
|
7058
|
+
|
|
7059
|
+
// We create an array of buffers so strings don't expire until MAX_TEXTFORMAT_BUFFERS invocations
|
|
7060
|
+
static char buffers[MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
|
7061
|
+
static int index = 0;
|
|
7062
|
+
|
|
7063
|
+
char *currentBuffer = buffers[index];
|
|
7064
|
+
memset(currentBuffer, 0, MAX_TEXT_BUFFER_LENGTH); // Clear buffer before using
|
|
7065
|
+
|
|
7066
|
+
va_list args;
|
|
7067
|
+
va_start(args, text);
|
|
7068
|
+
vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
|
7069
|
+
va_end(args);
|
|
7070
|
+
|
|
7071
|
+
index += 1; // Move to next buffer for next function call
|
|
7072
|
+
if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
|
7073
|
+
|
|
7074
|
+
return currentBuffer;
|
|
7075
|
+
}
|
|
7076
|
+
#endif // !SUPPORT_MODULE_RTEXT
|